diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index a295f461e5..0000000000 --- a/docs/CNAME +++ /dev/null @@ -1,2 +0,0 @@ -asyncdisplaykit.org - diff --git a/docs/LICENSE.md b/docs/LICENSE.md deleted file mode 100644 index 4bb498ec63..0000000000 --- a/docs/LICENSE.md +++ /dev/null @@ -1,420 +0,0 @@ ---- -layout: page -title: License -permalink: /license/ ---- - -AsyncDisplayKit is free software under the BSD -license. - -Code examples and sample -projects are licensed as follows: - - 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. - -All other AsyncDisplayKit documentation is licensed CC-BY-4.0. - - Attribution 4.0 International - - ======================================================================= - - Creative Commons Corporation ("Creative Commons") is not a law firm and - does not provide legal services or legal advice. Distribution of - Creative Commons public licenses does not create a lawyer-client or - other relationship. Creative Commons makes its licenses and related - information available on an "as-is" basis. Creative Commons gives no - warranties regarding its licenses, any material licensed under their - terms and conditions, or any related information. Creative Commons - disclaims all liability for damages resulting from their use to the - fullest extent possible. - - Using Creative Commons Public Licenses - - Creative Commons public licenses provide a standard set of terms and - conditions that creators and other rights holders may use to share - original works of authorship and other material subject to copyright - and certain other rights specified in the public license below. The - following considerations are for informational purposes only, are not - exhaustive, and do not form part of our licenses. - - Considerations for licensors: Our public licenses are - intended for use by those authorized to give the public - permission to use material in ways otherwise restricted by - copyright and certain other rights. Our licenses are - irrevocable. Licensors should read and understand the terms - and conditions of the license they choose before applying it. - Licensors should also secure all rights necessary before - applying our licenses so that the public can reuse the - material as expected. Licensors should clearly mark any - material not subject to the license. This includes other CC- - licensed material, or material used under an exception or - limitation to copyright. More considerations for licensors: - wiki.creativecommons.org/Considerations_for_licensors - - Considerations for the public: By using one of our public - licenses, a licensor grants the public permission to use the - licensed material under specified terms and conditions. If - the licensor's permission is not necessary for any reason--for - example, because of any applicable exception or limitation to - copyright--then that use is not regulated by the license. Our - licenses grant only permissions under copyright and certain - other rights that a licensor has authority to grant. Use of - the licensed material may still be restricted for other - reasons, including because others have copyright or other - rights in the material. A licensor may make special requests, - such as asking that all changes be marked or described. - Although not required by our licenses, you are encouraged to - respect those requests where reasonable. More_considerations - for the public: - wiki.creativecommons.org/Considerations_for_licensees - - ======================================================================= - - Creative Commons Attribution 4.0 International Public License - - By exercising the Licensed Rights (defined below), You accept and agree - to be bound by the terms and conditions of this Creative Commons - Attribution 4.0 International Public License ("Public License"). To the - extent this Public License may be interpreted as a contract, You are - granted the Licensed Rights in consideration of Your acceptance of - these terms and conditions, and the Licensor grants You such rights in - consideration of benefits the Licensor receives from making the - Licensed Material available under these terms and conditions. - - - Section 1 -- Definitions. - - a. Adapted Material means material subject to Copyright and Similar - Rights that is derived from or based upon the Licensed Material - and in which the Licensed Material is translated, altered, - arranged, transformed, or otherwise modified in a manner requiring - permission under the Copyright and Similar Rights held by the - Licensor. For purposes of this Public License, where the Licensed - Material is a musical work, performance, or sound recording, - Adapted Material is always produced where the Licensed Material is - synched in timed relation with a moving image. - - b. Adapter's License means the license You apply to Your Copyright - and Similar Rights in Your contributions to Adapted Material in - accordance with the terms and conditions of this Public License. - - c. Copyright and Similar Rights means copyright and/or similar rights - closely related to copyright including, without limitation, - performance, broadcast, sound recording, and Sui Generis Database - Rights, without regard to how the rights are labeled or - categorized. For purposes of this Public License, the rights - specified in Section 2(b)(1)-(2) are not Copyright and Similar - Rights. - - d. Effective Technological Measures means those measures that, in the - absence of proper authority, may not be circumvented under laws - fulfilling obligations under Article 11 of the WIPO Copyright - Treaty adopted on December 20, 1996, and/or similar international - agreements. - - e. Exceptions and Limitations means fair use, fair dealing, and/or - any other exception or limitation to Copyright and Similar Rights - that applies to Your use of the Licensed Material. - - f. Licensed Material means the artistic or literary work, database, - or other material to which the Licensor applied this Public - License. - - g. Licensed Rights means the rights granted to You subject to the - terms and conditions of this Public License, which are limited to - all Copyright and Similar Rights that apply to Your use of the - Licensed Material and that the Licensor has authority to license. - - h. Licensor means the individual(s) or entity(ies) granting rights - under this Public License. - - i. Share means to provide material to the public by any means or - process that requires permission under the Licensed Rights, such - as reproduction, public display, public performance, distribution, - dissemination, communication, or importation, and to make material - available to the public including in ways that members of the - public may access the material from a place and at a time - individually chosen by them. - - j. Sui Generis Database Rights means rights other than copyright - resulting from Directive 96/9/EC of the European Parliament and of - the Council of 11 March 1996 on the legal protection of databases, - as amended and/or succeeded, as well as other essentially - equivalent rights anywhere in the world. - - k. You means the individual or entity exercising the Licensed Rights - under this Public License. Your has a corresponding meaning. - - - Section 2 -- Scope. - - a. License grant. - - 1. Subject to the terms and conditions of this Public License, - the Licensor hereby grants You a worldwide, royalty-free, - non-sublicensable, non-exclusive, irrevocable license to - exercise the Licensed Rights in the Licensed Material to: - - a. reproduce and Share the Licensed Material, in whole or - in part; and - - b. produce, reproduce, and Share Adapted Material. - - 2. Exceptions and Limitations. For the avoidance of doubt, where - Exceptions and Limitations apply to Your use, this Public - License does not apply, and You do not need to comply with - its terms and conditions. - - 3. Term. The term of this Public License is specified in Section - 6(a). - - 4. Media and formats; technical modifications allowed. The - Licensor authorizes You to exercise the Licensed Rights in - all media and formats whether now known or hereafter created, - and to make technical modifications necessary to do so. The - Licensor waives and/or agrees not to assert any right or - authority to forbid You from making technical modifications - necessary to exercise the Licensed Rights, including - technical modifications necessary to circumvent Effective - Technological Measures. For purposes of this Public License, - simply making modifications authorized by this Section 2(a) - (4) never produces Adapted Material. - - 5. Downstream recipients. - - a. Offer from the Licensor -- Licensed Material. Every - recipient of the Licensed Material automatically - receives an offer from the Licensor to exercise the - Licensed Rights under the terms and conditions of this - Public License. - - b. No downstream restrictions. You may not offer or impose - any additional or different terms or conditions on, or - apply any Effective Technological Measures to, the - Licensed Material if doing so restricts exercise of the - Licensed Rights by any recipient of the Licensed - Material. - - 6. No endorsement. Nothing in this Public License constitutes or - may be construed as permission to assert or imply that You - are, or that Your use of the Licensed Material is, connected - with, or sponsored, endorsed, or granted official status by, - the Licensor or others designated to receive attribution as - provided in Section 3(a)(1)(A)(i). - - b. Other rights. - - 1. Moral rights, such as the right of integrity, are not - licensed under this Public License, nor are publicity, - privacy, and/or other similar personality rights; however, to - the extent possible, the Licensor waives and/or agrees not to - assert any such rights held by the Licensor to the limited - extent necessary to allow You to exercise the Licensed - Rights, but not otherwise. - - 2. Patent and trademark rights are not licensed under this - Public License. - - 3. To the extent possible, the Licensor waives any right to - collect royalties from You for the exercise of the Licensed - Rights, whether directly or through a collecting society - under any voluntary or waivable statutory or compulsory - licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties. - - - Section 3 -- License Conditions. - - Your exercise of the Licensed Rights is expressly made subject to the - following conditions. - - a. Attribution. - - 1. If You Share the Licensed Material (including in modified - form), You must: - - a. retain the following if it is supplied by the Licensor - with the Licensed Material: - - i. identification of the creator(s) of the Licensed - Material and any others designated to receive - attribution, in any reasonable manner requested by - the Licensor (including by pseudonym if - designated); - - ii. a copyright notice; - - iii. a notice that refers to this Public License; - - iv. a notice that refers to the disclaimer of - warranties; - - v. a URI or hyperlink to the Licensed Material to the - extent reasonably practicable; - - b. indicate if You modified the Licensed Material and - retain an indication of any previous modifications; and - - c. indicate the Licensed Material is licensed under this - Public License, and include the text of, or the URI or - hyperlink to, this Public License. - - 2. You may satisfy the conditions in Section 3(a)(1) in any - reasonable manner based on the medium, means, and context in - which You Share the Licensed Material. For example, it may be - reasonable to satisfy the conditions by providing a URI or - hyperlink to a resource that includes the required - information. - - 3. If requested by the Licensor, You must remove any of the - information required by Section 3(a)(1)(A) to the extent - reasonably practicable. - - 4. If You Share Adapted Material You produce, the Adapter's - License You apply must not prevent recipients of the Adapted - Material from complying with this Public License. - - - Section 4 -- Sui Generis Database Rights. - - Where the Licensed Rights include Sui Generis Database Rights that - apply to Your use of the Licensed Material: - - a. for the avoidance of doubt, Section 2(a)(1) grants You the right - to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database; - - b. if You include all or a substantial portion of the database - contents in a database in which You have Sui Generis Database - Rights, then the database in which You have Sui Generis Database - Rights (but not its individual contents) is Adapted Material; and - - c. You must comply with the conditions in Section 3(a) if You Share - all or a substantial portion of the contents of the database. - - For the avoidance of doubt, this Section 4 supplements and does not - replace Your obligations under this Public License where the Licensed - Rights include other Copyright and Similar Rights. - - - Section 5 -- Disclaimer of Warranties and Limitation of Liability. - - a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE - EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS - AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF - ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, - IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, - WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, - ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT - KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT - ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. - - b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE - TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, - NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, - INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, - COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR - USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN - ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR - DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR - IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. - - c. The disclaimer of warranties and limitation of liability provided - above shall be interpreted in a manner that, to the extent - possible, most closely approximates an absolute disclaimer and - waiver of all liability. - - - Section 6 -- Term and Termination. - - a. This Public License applies for the term of the Copyright and - Similar Rights licensed here. However, if You fail to comply with - this Public License, then Your rights under this Public License - terminate automatically. - - b. Where Your right to use the Licensed Material has terminated under - Section 6(a), it reinstates: - - 1. automatically as of the date the violation is cured, provided - it is cured within 30 days of Your discovery of the - violation; or - - 2. upon express reinstatement by the Licensor. - - For the avoidance of doubt, this Section 6(b) does not affect any - right the Licensor may have to seek remedies for Your violations - of this Public License. - - c. For the avoidance of doubt, the Licensor may also offer the - Licensed Material under separate terms or conditions or stop - distributing the Licensed Material at any time; however, doing so - will not terminate this Public License. - - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public - License. - - - Section 7 -- Other Terms and Conditions. - - a. The Licensor shall not be bound by any additional or different - terms or conditions communicated by You unless expressly agreed. - - b. Any arrangements, understandings, or agreements regarding the - Licensed Material not stated herein are separate from and - independent of the terms and conditions of this Public License. - - - Section 8 -- Interpretation. - - a. For the avoidance of doubt, this Public License does not, and - shall not be interpreted to, reduce, limit, restrict, or impose - conditions on any use of the Licensed Material that could lawfully - be made without permission under this Public License. - - b. To the extent possible, if any provision of this Public License is - deemed unenforceable, it shall be automatically reformed to the - minimum extent necessary to make it enforceable. If the provision - cannot be reformed, it shall be severed from this Public License - without affecting the enforceability of the remaining terms and - conditions. - - c. No term or condition of this Public License will be waived and no - failure to comply consented to unless expressly agreed to by the - Licensor. - - d. Nothing in this Public License constitutes or may be interpreted - as a limitation upon, or waiver of, any privileges and immunities - that apply to the Licensor or You, including from the legal - processes of any jurisdiction or authority. - - - ======================================================================= - - Creative Commons is not a party to its public licenses. - Notwithstanding, Creative Commons may elect to apply one of its public - licenses to material it publishes and in those instances will be - considered the "Licensor." Except for the limited purpose of indicating - that material is shared under a Creative Commons public license or as - otherwise permitted by the Creative Commons policies published at - creativecommons.org/policies, Creative Commons does not authorize the - use of the trademark "Creative Commons" or any other trademark or logo - of Creative Commons without its prior written consent including, - without limitation, in connection with any unauthorized modifications - to any of its public licenses or any other arrangements, - understandings, or agreements concerning use of licensed material. For - the avoidance of doubt, this paragraph does not form part of the public - licenses. - - Creative Commons may be contacted at creativecommons.org. diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 05980d3818..0000000000 --- a/docs/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Documentation - -## Building - -You need Jekyll and appledoc. See `build.sh`. - -## License - -See LICENSE.md. diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index 0d5f309f67..0000000000 --- a/docs/_config.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Site settings -title: AsyncDisplayKit -description: Smooth asynchronous user interfaces for iOS apps. -baseurl: "" -url: "http://asyncdisplaykit.org" - -# Build settings -highlighter: pygments -markdown: redcarpet - -exclude: -- README.md -- build.sh diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html deleted file mode 100644 index 2714963def..0000000000 --- a/docs/_includes/footer.html +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/docs/_includes/head.html b/docs/_includes/head.html deleted file mode 100644 index a9e7efbdea..0000000000 --- a/docs/_includes/head.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - {% if page.title %}{{ page.title }} — {% endif %}AsyncDisplayKit - - - - - - - diff --git a/docs/_includes/header.html b/docs/_includes/header.html deleted file mode 100644 index aebb67cdf1..0000000000 --- a/docs/_includes/header.html +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html deleted file mode 100644 index bdf5a388da..0000000000 --- a/docs/_layouts/default.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - {% include head.html %} - - - - {% include header.html %} - -
-
- {{ content }} -
-
- - {% include footer.html %} - - - - diff --git a/docs/_layouts/docs.html b/docs/_layouts/docs.html deleted file mode 100644 index 65c07040aa..0000000000 --- a/docs/_layouts/docs.html +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: default -sectionid: docs ---- -
- -
-

- {{ page.title }} - [edit] -

-
- -
- {{ content }} -
- -
- {% if page.prev %} - ← prev - {% endif %} - {% if page.next %} - next → - {% endif %} -
- -
diff --git a/docs/_layouts/page.html b/docs/_layouts/page.html deleted file mode 100644 index 8e7ccf7a15..0000000000 --- a/docs/_layouts/page.html +++ /dev/null @@ -1,16 +0,0 @@ ---- -layout: default ---- -
- - {% if page.shouldDisplayTitle %} -
-

{{ page.title }}

-
- {% endif %} - -
- {{ content }} -
- -
diff --git a/docs/_layouts/post.html b/docs/_layouts/post.html deleted file mode 100644 index 675596fb1c..0000000000 --- a/docs/_layouts/post.html +++ /dev/null @@ -1,15 +0,0 @@ ---- -layout: default ---- -
- -
-

{{ page.title }}

- -
- -
- {{ content }} -
- -
diff --git a/docs/_sass/_base.scss b/docs/_sass/_base.scss deleted file mode 100644 index 7d353be258..0000000000 --- a/docs/_sass/_base.scss +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Reset some basic elements - */ -body, h1, h2, h3, h4, h5, h6, -p, blockquote, pre, hr, -dl, dd, ol, ul, figure { - margin: 0; - padding: 0; -} - - - -/** - * Basic styling - */ -body { - font-family: $base-font-family; - font-size: $base-font-size; - line-height: $base-line-height; - font-weight: 300; - color: $text-color; - background-color: $background-color; - -webkit-text-size-adjust: 100%; -} - - - -/** - * Set `margin-bottom` to maintain vertical rhythm - */ -h1, h2, h3, h4, h5, h6, -p, blockquote, pre, -ul, ol, dl, figure, -%vertical-rhythm { - margin-bottom: $spacing-unit / 2; -} - - - -/** - * Images - */ -img { - max-width: 100%; - vertical-align: middle; -} - - - -/** - * Figures - */ -figure > img { - display: block; -} - -figcaption { - font-size: $small-font-size; -} - - - -/** - * Lists - */ -ul, ol { - margin-left: $spacing-unit; -} - -li { - > ul, - > ol { - margin-bottom: 0; - } -} - - - -/** - * Headings - */ -h1, h2, h3, h4, h5, h6 { - font-weight: 300; -} - - - -/** - * Links - */ -a { - color: $brand-color; - text-decoration: none; - - &:visited { - color: darken($brand-color, 15%); - } - - &:hover { - color: $text-color; - text-decoration: underline; - } -} - - - -/** - * Blockquotes - */ -blockquote { - color: $grey-color; - border-left: 4px solid $grey-color-light; - padding-left: $spacing-unit / 2; - font-size: 18px; - letter-spacing: -1px; - font-style: italic; - - > :last-child { - margin-bottom: 0; - } -} - - - -/** - * Code formatting - */ -pre, -code { - font-family: Monaco, monospace; - font-size: 14px; - border: 1px solid #afe4ff; - border-radius: 3px; - background-color: #fafdff; -} - -code { - padding: 1px 5px; -} - -pre { - padding: 8px 12px; - overflow-x: scroll; - - > code { - border: 0; - padding-right: 0; - padding-left: 0; - } -} - - - -/** - * Wrapper - */ -.wrapper { - max-width: -webkit-calc(800px - (#{$spacing-unit} * 2)); - max-width: calc(800px - (#{$spacing-unit} * 2)); - margin-right: auto; - margin-left: auto; - padding-right: $spacing-unit; - padding-left: $spacing-unit; - @extend %clearfix; - - @include media-query($on-laptop) { - max-width: -webkit-calc(800px - (#{$spacing-unit})); - max-width: calc(800px - (#{$spacing-unit})); - padding-right: $spacing-unit / 2; - padding-left: $spacing-unit / 2; - } -} - - - -/** - * Clearfix - */ -%clearfix { - - &:after { - content: ""; - display: table; - clear: both; - } -} - - - -/** - * Icons - */ -.icon { - - > svg { - display: inline-block; - width: 16px; - height: 16px; - vertical-align: middle; - - path { - fill: $grey-color; - } - } -} diff --git a/docs/_sass/_layout.scss b/docs/_sass/_layout.scss deleted file mode 100644 index 2eb740fa67..0000000000 --- a/docs/_sass/_layout.scss +++ /dev/null @@ -1,265 +0,0 @@ -/** - * Site header - */ -.site-header { - border-top: 5px solid $grey-color-dark; - border-bottom: 1px solid $grey-color-light; - min-height: 56px; - background-color: #f8f8f8; - - // Positioning context for the mobile navigation icon - position: relative; -} - -.site-title { - font-size: 26px; - line-height: 56px; - letter-spacing: -1px; - margin-bottom: 0; - float: left; - - &, - &:visited { - color: $grey-color-dark; - } - &:hover { - text-decoration: none; - } -} - -.site-nav { - float: right; - line-height: 56px; - - .menu-icon { - display: none; - } - - .page-link { - color: $grey-color; - line-height: $base-line-height; - - // Gaps between nav items, but not on the first one - &:not(:first-child) { - margin-left: 20px; - } - - &:hover { - color: $text-color; - } - } - - .page-link-active { - color: $text-color; - } - - @include media-query($on-palm) { - position: absolute; - top: 9px; - right: 30px; - background-color: $background-color; - border: 1px solid $grey-color-light; - border-radius: 5px; - text-align: right; - - .menu-icon { - display: block; - float: right; - width: 36px; - height: 26px; - line-height: 0; - padding-top: 10px; - text-align: center; - - > svg { - width: 18px; - height: 15px; - - path { - fill: $grey-color-dark; - } - } - } - - .trigger { - clear: both; - display: none; - } - - &:hover .trigger { - display: block; - padding-bottom: 5px; - } - - .page-link { - display: block; - padding: 5px 10px; - } - } -} - - - -/** - * Site footer - */ -.site-footer { - border-top: 1px solid $grey-color-light; - padding: $spacing-unit 0; -} - -.footer-heading { - font-size: 18px; - margin-bottom: $spacing-unit / 2; -} - -.contact-list, -.social-media-list { - list-style: none; - margin-left: 0; -} - -.footer-col-wrapper { - font-size: 11px; - color: $grey-color; - margin-left: -$spacing-unit / 2; - @extend %clearfix; -} - -.footer-col { - float: left; - margin-bottom: $spacing-unit / 2; - padding-left: $spacing-unit / 2; -} - -.footer-col-left { - width: -webkit-calc(50% - (#{$spacing-unit} / 2)); - width: calc(50% - (#{$spacing-unit} / 2)); -} - -.footer-col-right { - text-align: right; - width: -webkit-calc(50% - (#{$spacing-unit} / 2)); - width: calc(50% - (#{$spacing-unit} / 2)); -} - -@include media-query($on-laptop) { - .footer-col-left { - width: -webkit-calc(50% - (#{$spacing-unit} / 2)); - width: calc(50% - (#{$spacing-unit} / 2)); - } - - .footer-col-right { - width: -webkit-calc(100% - (#{$spacing-unit} / 2)); - width: calc(100% - (#{$spacing-unit} / 2)); - } -} - -@include media-query($on-palm) { - .footer-col { - float: none; - width: -webkit-calc(100% - (#{$spacing-unit} / 2)); - width: calc(100% - (#{$spacing-unit} / 2)); - } -} - - - -/** - * Page content - */ -.page-content { - padding: $spacing-unit 0; - background-color: white; -} - -.page-heading { - font-size: 20px; -} - -.post-list { - margin-left: 0; - list-style: none; - - > li { - margin-bottom: $spacing-unit; - } -} - -.post-meta { - font-size: $small-font-size; - color: $grey-color; -} - -.post-link { - display: block; - font-size: 24px; -} - - - -/** - * Posts - */ -.post-header { - margin-bottom: $spacing-unit; -} - -.post-title { - font-size: 42px; - letter-spacing: -1px; - line-height: 1; - - @include media-query($on-laptop) { - font-size: 36px; - } - - .edit-page-link { - font-size: 18px; - } -} - -.post-content { - margin-bottom: $spacing-unit; - - h2 { - font-size: 32px; - - @include media-query($on-laptop) { - font-size: 28px; - } - } - - h3 { - font-size: 26px; - - @include media-query($on-laptop) { - font-size: 22px; - } - } - - h4 { - font-size: 20px; - - @include media-query($on-laptop) { - font-size: 18px; - } - } -} - - - -/** - * Docs - */ -.docs-prevnext { - @extend %clearfix; -} - -.docs-prev { - float: left; -} - -.docs-next { - float: right; -} diff --git a/docs/_sass/_syntax-highlighting.scss b/docs/_sass/_syntax-highlighting.scss deleted file mode 100644 index 3758fdb458..0000000000 --- a/docs/_sass/_syntax-highlighting.scss +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Syntax highlighting styles - */ - -/* not official Xcode colors, but looks better on the web */ -$xc-black: black; -$xc-green: #008d14; -$xc-red: #b72748; -$xc-blue: #103ffb; -$xc-turquoise: #3a95ba; - -.highlight { - background: #fff; - @extend %vertical-rhythm; - - .c { color: $xc-green; font-style: italic } // Comment - .err { color: #a61717; background-color: #e3d2d2 } // Error - .k { color: $xc-blue} // Keyword - .o { } // Operator - .cm { color: $xc-green; font-style: italic } // Comment.Multiline - .cp { color: $xc-red} // Comment.Preproc - .c1 { color: $xc-green; font-style: italic } // Comment.Single - .cs { color: $xc-green; font-weight: bold; font-style: italic } // Comment.Special - .gd { color: #000; background-color: #fdd } // Generic.Deleted - .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific - .ge { font-style: italic } // Generic.Emph - .gr { color: #a00 } // Generic.Error - .gh { color: #999 } // Generic.Heading - .gi { color: #000; background-color: #dfd } // Generic.Inserted - .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific - .go { color: #888 } // Generic.Output - .gp { color: #555 } // Generic.Prompt - .gs { font-weight: bold } // Generic.Strong - .gu { color: #aaa } // Generic.Subheading - .gt { color: #a00 } // Generic.Traceback - .kc { color: orange} // Keyword.Constant - .kd { color: orange} // Keyword.Declaration - .kp { color: $xc-green} // Keyword.Pseudo - .kr { color: $xc-green} // Keyword.Reserved - .kt { color: $xc-blue} // Keyword.Type - .m { color: orange } // Literal.Number - .s { color: $xc-red } // Literal.String - .na { color: orange } // Name.Attribute - .nb { color: $xc-blue } // Name.Builtin - .nc { color: $xc-turquoise } // Name.Class - .no { color: orange } // Name.Constant - .ni { color: orange } // Name.Entity - .ne { color: orange } // Name.Exception - .nf { } // Name.Function - .nn { color: orange } // Name.Namespace - .nt { color: orange } // Name.Tag - .nv { } // Name.Variable - .ow { } // Operator.Word - .w { color: #bbb } // Text.Whitespace - .mf {} // Literal.Number.Float - .mh { color: $xc-black } // Literal.Number.Hex - .mi { color: $xc-black } // Literal.Number.Integer - .mo { color: $xc-black } // Literal.Number.Oct - .il { color: $xc-black } // Literal.Number.Integer.Long - .sb { color: #d14 } // Literal.String.Backtick - .sc { color: #d14 } // Literal.String.Char - .sd { color: #d14 } // Literal.String.Doc - .s2 { color: #d14 } // Literal.String.Double - .se { color: #d14 } // Literal.String.Escape - .sh { color: #d14 } // Literal.String.Heredoc - .si { color: #d14 } // Literal.String.Interpol - .sx { color: #d14 } // Literal.String.Other - .sr { color: orange } // Literal.String.Regex - .s1 { color: $xc-red } // Literal.String.Single - .ss { color: $xc-red } // Literal.String.Symbol - .bp { color: $xc-turquoise } // Name.Builtin.Pseudo - .vc { color: $xc-turquoise } // Name.Variable.Class - .vg { color: $xc-black } // Name.Variable.Global - .vi { color: orange } // Name.Variable.Instance - .nl { color: $xc-turquoise } -} diff --git a/docs/assets/guide/1-shuffle-crop.png b/docs/assets/guide/1-shuffle-crop.png deleted file mode 100644 index d1e0a83b0c..0000000000 Binary files a/docs/assets/guide/1-shuffle-crop.png and /dev/null differ diff --git a/docs/assets/guide/1-shuffle.png b/docs/assets/guide/1-shuffle.png deleted file mode 100644 index 9188eebf8a..0000000000 Binary files a/docs/assets/guide/1-shuffle.png and /dev/null differ diff --git a/docs/assets/logo-square.png b/docs/assets/logo-square.png deleted file mode 100755 index 82ad66c69e..0000000000 Binary files a/docs/assets/logo-square.png and /dev/null differ diff --git a/docs/assets/logo.png b/docs/assets/logo.png deleted file mode 100755 index dce1ebc950..0000000000 Binary files a/docs/assets/logo.png and /dev/null differ diff --git a/docs/assets/node-view-layer.png b/docs/assets/node-view-layer.png deleted file mode 100755 index 544294af8f..0000000000 Binary files a/docs/assets/node-view-layer.png and /dev/null differ diff --git a/docs/build.sh b/docs/build.sh deleted file mode 100755 index c532bb0d6b..0000000000 --- a/docs/build.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -set -e - -HEADERS=`ls ../AsyncDisplayKit/*.h ../AsyncDisplayKit/Details/ASRangeController.h ../AsyncDisplayKit/Layout/*.h` - -rm -rf htdocs appledoc - -jekyll build --destination htdocs - -appledoc \ - --no-create-docset \ - --create-html \ - --exit-threshold 2 \ - --no-repeat-first-par \ - --no-merge-categories \ - --explicit-crossref \ - --warn-missing-output-path \ - --warn-missing-company-id \ - --warn-undocumented-object \ - --warn-undocumented-member \ - --warn-empty-description \ - --warn-unknown-directive \ - --warn-invalid-crossref \ - --warn-missing-arg \ - --project-name AsyncDisplayKit \ - --project-company Facebook \ - --company-id "com.facebook" \ - --output appledoc \ - $HEADERS - -mv appledoc/html htdocs/appledoc - -rmdir appledoc diff --git a/docs/css/main.scss b/docs/css/main.scss deleted file mode 100755 index 4417ff0713..0000000000 --- a/docs/css/main.scss +++ /dev/null @@ -1,49 +0,0 @@ ---- -# Only the main Sass file needs front matter (the dashes are enough) ---- -@charset "utf-8"; - - - -// Our variables -$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -$base-font-size: 16px; -$small-font-size: $base-font-size * 0.875; -$base-line-height: 1.5; - -$spacing-unit: 30px; - -$text-color: #111; -$background-color: #f8f8f8; -$brand-color: #21b6ff; - -$grey-color: #828282; -$grey-color-light: lighten($grey-color, 40%); -$grey-color-dark: darken($grey-color, 25%); - -$on-palm: 600px; -$on-laptop: 800px; - - - -// Using media queries with like this: -// @include media-query($palm) { -// .wrapper { -// padding-right: $spacing-unit / 2; -// padding-left: $spacing-unit / 2; -// } -// } -@mixin media-query($device) { - @media screen and (max-width: $device) { - @content; - } -} - - - -// Import partials from `sass_dir` (defaults to `_sass`) -@import - "base", - "layout", - "syntax-highlighting" -; diff --git a/docs/guide/1-introduction.md b/docs/guide/1-introduction.md deleted file mode 100644 index d923c0a215..0000000000 --- a/docs/guide/1-introduction.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -layout: docs -title: Getting started -permalink: /guide/ -next: guide/2/ ---- - -## Concepts - -AsyncDisplayKit's basic unit is the *node*. ASDisplayNode is an abstraction -over UIView, which in turn is an abstraction over CALayer. Unlike views, which -can only be used on the main thread, nodes are thread-safe: you can -instantiate and configure entire hierarchies of them in parallel on background -threads. - -To keep its user interface smooth and responsive, your app should render at 60 -frames per second — the gold standard on iOS. This means the main thread -has one-sixtieth of a second to push each frame. That's 16 milliseconds to -execute all layout and drawing code! And because of system overhead, your code -usually has less than ten milliseconds to run before it causes a frame drop. - -AsyncDisplayKit lets you move image decoding, text sizing and rendering, and -other expensive UI operations off the main thread. It has other tricks up its -sleeve too... but we'll get to that later. :] - -## Nodes as drop-in view replacements - -If you're used to working with views, you already know how to use nodes. The -node API is similar to UIView's, with some additional conveniences — for -example, you can access common CALayer properties directly. To add a node to -an existing view or layer hierarchy, use its `node.view` or `node.layer`. - -AsyncDisplayKit's core components include: - -* *ASDisplayNode*. Counterpart to UIView — subclass to make custom nodes. -* *ASControlNode*. Analogous to UIControl — subclass to make buttons. -* *ASImageNode*. Like UIImageView — decodes images asynchronously. -* *ASTextNode*. Like UITextView — built on TextKit with full-featured - rich text support. -* *ASTableView* and *ASCollectionView*. UITableView and UICollectionView - subclasses that support nodes. - -You can use these as drop-in replacements for their UIKit counterparts. While -ASDK works most effectively with fully node-based hierarchies, even replacing -individual views with nodes can improve performance. - -Let's look at an example. - -We'll start out by using nodes synchronously on the main thread — the -same way you already use views. This code is a familiar sight in custom view -controller `-loadView` implementations: - -```objective-c -_imageView = [[UIImageView alloc] init]; -_imageView.image = [UIImage imageNamed:@"hello"]; -_imageView.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f); -[self.view addSubview:_imageView]; -``` - -We can replace it with the following node-based code: - -```objective-c -_imageNode = [[ASImageNode alloc] init]; -_imageNode.backgroundColor = [UIColor lightGrayColor]; -_imageNode.image = [UIImage imageNamed:@"hello"]; -_imageNode.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f); -[self.view addSubview:_imageNode.view]; -``` - -This doesn't take advantage of ASDK's asynchronous sizing and layout -functionality, but it's already an improvement. The first block of code -synchronously decodes `hello.png` on the main thread; the second starts -decoding the image on a background thread, possibly on a different CPU core. - -(Note that we're setting a placeholder background colour on the node, "holding -its place" onscreen until the real content appears. This works well with -images but less so with text — people expect text to appear instantly, -with images loading in after a slight delay. We'll discuss techniques to -improve this later on.) - -## Button nodes - -ASImageNode and ASTextNode both inherit from ASControlNode, so you can use them -as buttons. Let's say we're making a music player and we want to add a -(non-skeuomorphic, iOS 7-style) shuffle button: - -[![shuffle]({{ site.baseurl }}/assets/guide/1-shuffle-crop.png)]({{ site.baseurl }}/assets/guide/1-shuffle.png) - -Our view controller will look something like this: - -```objective-c -- (void)viewDidLoad -{ - [super viewDidLoad]; - - // attribute a string - NSDictionary *attrs = @{ - NSFontAttributeName: [UIFont systemFontOfSize:12.0f], - NSForegroundColorAttributeName: [UIColor redColor], - }; - NSAttributedString *string = [[NSAttributedString alloc] initWithString:@"shuffle" - attributes:attrs]; - - // create the node - _shuffleNode = [[ASTextNode alloc] init]; - _shuffleNode.attributedString = string; - - // configure the button - _shuffleNode.userInteractionEnabled = YES; // opt into touch handling - [_shuffleNode addTarget:self - action:@selector(buttonTapped:) - forControlEvents:ASControlNodeEventTouchUpInside]; - - // size all the things - CGRect b = self.view.bounds; // convenience - CGSize size = [_shuffleNode measure:CGSizeMake(b.size.width, FLT_MAX)]; - CGPoint origin = CGPointMake(roundf( (b.size.width - size.width) / 2.0f ), - roundf( (b.size.height - size.height) / 2.0f )); - _shuffleNode.frame = (CGRect){ origin, size }; - - // add to our view - [self.view addSubview:_shuffleNode.view]; -} - -- (void)buttonTapped:(id)sender -{ - NSLog(@"tapped!"); -} -``` - -This works as you would expect. Unfortunately, this button is only 14½ -points tall — nowhere near the standard 44×44 minimum tap target -size — and it's very difficult to tap. We could solve this by -subclassing the text node and overriding `-hitTest:withEvent:`. We could even -force the text view to have a minimum height during layout. But wouldn't it be -nice if there were a more elegant way? - -```objective-c - // size all the things - /* ... */ - - // make the tap target taller - CGFloat extendY = roundf( (44.0f - size.height) / 2.0f ); - _shuffleNode.hitTestSlop = UIEdgeInsetsMake(-extendY, 0.0f, -extendY, 0.0f); -``` - -Et voilà! *Hit-test slops* work on all nodes, and are a nice example of what -this new abstraction enables. - -Next up, making your own nodes! diff --git a/docs/guide/2-custom-nodes.md b/docs/guide/2-custom-nodes.md deleted file mode 100644 index 6d67ed3a05..0000000000 --- a/docs/guide/2-custom-nodes.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -layout: docs -title: Custom nodes -permalink: /guide/2/ -prev: guide/ -next: guide/3/ ---- - -## View hierarchies - -Sizing and layout of custom view hierarchies are typically done all at once on -the main thread. For example, a custom UIView that minimally encloses a text -view and an image view might look like this: - -```objective-c -- (CGSize)sizeThatFits:(CGSize)size -{ - // size the image - CGSize imageSize = [_imageView sizeThatFits:size]; - - // size the text view - CGSize maxTextSize = CGSizeMake(size.width - imageSize.width, size.height); - CGSize textSize = [_textView sizeThatFits:maxTextSize]; - - // make sure everything fits - CGFloat minHeight = MAX(imageSize.height, textSize.height); - return CGSizeMake(size.width, minHeight); -} - -- (void)layoutSubviews -{ - CGSize size = self.bounds.size; // convenience - - // size and layout the image - CGSize imageSize = [_imageView sizeThatFits:size]; - _imageView.frame = CGRectMake(size.width - imageSize.width, 0.0f, - imageSize.width, imageSize.height); - - // size and layout the text view - CGSize maxTextSize = CGSizeMake(size.width - imageSize.width, size.height); - CGSize textSize = [_textView sizeThatFits:maxTextSize]; - _textView.frame = (CGRect){ CGPointZero, textSize }; -} -``` - -This isn't ideal. We're sizing our subviews twice — once to figure out -how big our view needs to be and once when laying it out — and while our -layout arithmetic is cheap and quick, we're also blocking the main thread on -expensive text sizing. - -We could improve the situation by manually cacheing our subviews' sizes, but -that solution comes with its own set of problems. Just adding `_imageSize` and -`_textSize` ivars wouldn't be enough: for example, if the text were to change, -we'd need to recompute its size. The boilerplate would quickly become -untenable. - -Further, even with a cache, we'll still be blocking the main thread on sizing -*sometimes*. We could try to shift sizing to a background thread with -`dispatch_async()`, but even if our own code is thread-safe, UIView methods are -documented to [only work on the main -thread](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html): - -> Manipulations to your application’s user interface must occur on the main -> thread. Thus, you should always call the methods of the UIView class from -> code running in the main thread of your application. The only time this may -> not be strictly necessary is when creating the view object itself but all -> other manipulations should occur on the main thread. - -This is a pretty deep rabbit hole. We could attempt to work around the fact -that UILabels and UITextViews cannot safely be sized on background threads by -manually creating a TextKit stack and sizing the text ourselves... but that's a -laborious duplication of work. Further, if UITextView's layout behaviour -changes in an iOS update, our sizing code will break. (And did we mention that -TextKit isn't thread-safe either?) - -## Node hierarchies - -Enter AsyncDisplayKit. Our custom node looks like this: - -```objective-c -#import - -... - -// perform expensive sizing operations on a background thread -- (CGSize)calculateSizeThatFits:(CGSize)constrainedSize -{ - // size the image - CGSize imageSize = [_imageNode measure:constrainedSize]; - - // size the text node - CGSize maxTextSize = CGSizeMake(constrainedSize.width - imageSize.width, - constrainedSize.height); - CGSize textSize = [_textNode measure:maxTextSize]; - - // make sure everything fits - CGFloat minHeight = MAX(imageSize.height, textSize.height); - return CGSizeMake(constrainedSize.width, minHeight); -} - -// do as little work as possible in main-thread layout -- (void)layout -{ - // layout the image using its cached size - CGSize imageSize = _imageNode.calculatedSize; - _imageNode.frame = CGRectMake(self.bounds.size.width - imageSize.width, 0.0f, - imageSize.width, imageSize.height); - - // layout the text view using its cached size - CGSize textSize = _textNode.calculatedSize; - _textNode.frame = (CGRect){ CGPointZero, textSize }; -} -``` - -ASImageNode and ASTextNode, like the rest of AsyncDisplayKit, are thread-safe, -so we can size them on background threads. The `-measure:` method is like -`-sizeThatFits:`, but with side effects: it caches both the argument -(`constrainedSizeForCalculatedSize`) and the result (`calculatedSize`) for -quick access later on — like in our now-snappy `-layout` implementation. - -As you can see, node hierarchies are sized and laid out in much the same way as -their view counterparts. Custom nodes do need to be written with a few things -in mind: - -* Nodes must recursively measure all of their subnodes in their - `-calculateSizeThatFits:` implementations. Note that the `-measure:` - machinery will only call `-calculateSizeThatFits:` if a new measurement pass - is needed (e.g., if the constrained size has changed). - -* Nodes should perform any other expensive pre-layout calculations in - `-calculateSizeThatFits:`, cacheing useful intermediate results in ivars as - appropriate. - -* Nodes should call `[self invalidateCalculatedSize]` when necessary. For - example, ASTextNode invalidates its calculated size when its - `attributedString` property is changed. - -For more examples of custom sizing and layout, along with a demo of -ASTextNode's features, check out `BlurbNode` and `KittenNode` in the -[Kittens](https://github.com/facebook/AsyncDisplayKit/tree/master/examples/Kittens) -sample project. - -## Custom drawing - -To guarantee thread safety in its highly-concurrent drawing system, the node -drawing API diverges substantially from UIView's. Instead of implementing -`-drawRect:`, you must: - -1. Define an internal "draw parameters" class for your custom node. This - class should be able to store any state your node needs to draw itself - — it can be a plain old NSObject or even a dictionary. - -2. Return a configured instance of your draw parameters class in - `-drawParametersForAsyncLayer:`. This method will always be called on the - main thread. - -3. Implement either `+drawRect:withParameters:isCancelled:isRasterizing:` or - `+displayWithParameters:isCancelled:`. Note that these are *class* methods - that will not have access to your node's state — only the draw - parameters object. They can be called on any thread and must be - thread-safe. - -For example, this node will draw a rainbow: - -```objective-c -@interface RainbowNode : ASDisplayNode -@end - -@implementation RainbowNode - -+ (void)drawRect:(CGRect)bounds - withParameters:(id)parameters - isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock - isRasterizing:(BOOL)isRasterizing -{ - // clear the backing store, but only if we're not rasterising into another layer - if (!isRasterizing) { - [[UIColor whiteColor] set]; - UIRectFill(bounds); - } - - // UIColor sadly lacks +indigoColor and +violetColor methods - NSArray *colors = @[ [UIColor redColor], - [UIColor orangeColor], - [UIColor yellowColor], - [UIColor greenColor], - [UIColor blueColor], - [UIColor purpleColor] ]; - CGFloat stripeHeight = roundf(bounds.size.height / (float)colors.count); - - // draw the stripes - for (UIColor *color in colors) { - CGRect stripe = CGRectZero; - CGRectDivide(bounds, &stripe, &bounds, stripeHeight, CGRectMinYEdge); - [color set]; - UIRectFill(stripe); - } -} - -@end -``` - -This could easily be extended to support vertical rainbows too, by adding a -`vertical` property to the node, exporting it in -`-drawParametersForAsyncLayer:`, and referencing it in -`+drawRect:withParameters:isCancelled:isRasterizing:`. More-complex nodes can -be supported in much the same way. - -For more on custom nodes, check out the [subclassing -header](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/ASDisplayNode%2BSubclasses.h) -or read on! diff --git a/docs/guide/3-asynchronous-display.md b/docs/guide/3-asynchronous-display.md deleted file mode 100644 index acc9f37911..0000000000 --- a/docs/guide/3-asynchronous-display.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -layout: docs -title: Asynchronous display -permalink: /guide/3/ -prev: guide/2/ -next: guide/4/ ---- - -## Realistic placeholders - -Nodes need to complete both a *measurement pass* and a *display pass* before -they're fully rendered. It's possible to force either step to happen -synchronously: call `-measure:` in `-layoutSubviews` to perform sizing on the -main thread, or set a node's `displaysAsynchronously` flag to NO to disable -ASDK's async display machinery. (AsyncDisplayKit can still improve your app's -performance even when rendering fully synchronously — more on that -later!) - -The recommended way to use ASDK is to only add nodes to your view hierarchy -once they've been sized. This avoids unsightly layout changes as the -measurement pass completes, but if you enable asynchronous display, it will -always be possible for a node to appear onscreen before its content has fully -rendered. We'll discuss techniques to minimise this shortly, but you should -take it into account and include *realistic placeholders* in your app designs. - -Once its measurement pass has completed, a node can accurately place all of its -subnodes onscreen — they'll just be blank. The easiest way to make a -realistic placeholder is to set static background colours on your subnodes. -This effect looks better than generic placeholder images because it varies -based on the content being loaded, and it works particularly well for opaque -images. You can also create visually-appealing placeholder nodes, like the -shimmery lines representing text in Paper as its stories are loaded, and swap -them out with your content nodes once they've finished displaying. - -## Working range - -So far, we've only discussed asynchronous sizing: toss a "create a node -hierarchy and measure it" block onto a background thread, then trampoline to -the main thread to add it to the view hierarchy when that's done. Ideally, as -much content as possible should be fully-rendered and ready to go as soon as -the user scrolls to it. This requires triggering display passes in advance. - -If your app's content is in a scroll view or can be paged through, like -Instagram's main feed or Paper's story strip, the solution is a *working -range*. A working range controller tracks the *visible range*, the subset of -content that's currently visible onscreen, and enqueues asynchronous rendering -for the next few screenfuls of content. As the user scrolls, a screenful or -two of previous content is preserved; the rest is cleared to conserve memory. -If she starts scrolling in the other direction, the working range trashes its -render queue and starts pre-rendering in the new direction of scroll — -and because of the buffer of previous content, this entire process will -typically be invisible. - -AsyncDisplayKit includes a generic working range controller, -`ASRangeController`. Its working range size can be tuned depending on your -app: if your nodes are simple, even an iPhone 4 can maintain a substantial -working range, but heavyweight nodes like Facebook stories are expensive and -need to be pruned quickly. - -```objective-c -ASRangeController *rangeController = [[ASRangeController alloc] init]; -rangeController.tuningParameters = (ASRangeTuningParameters){ - .leadingBufferScreenfuls = 2.0f; // two screenfuls in the direction of scroll - .trailingBufferScreenfuls = 0.5f; // one-half screenful in the other direction -}; -``` - -If you use a working range, you should profile your app and consider tuning it -differently on a per-device basis. iPhone 4 has 512MB of RAM and a single-core -A4 chipset, while iPhone 6 has 1GB of RAM and the orders-of-magnitude-faster -multicore A8 — and if your app supports iOS 7, it will be used on both. - -## ASTableView - -ASRangeController manages working ranges, but doesn't actually display content. -If your content is currently rendered in a UITableView, you can convert it to -use `ASTableView` and custom nodes — just subclass `ASCellNode` instead -of ASDisplayNode. ASTableView is a UITableView subclass that integrates -node-based cells and a working range. - -ASTableView doesn't let cells onscreen until their underlying nodes have been -sized, and as such can fully benefit from realistic placeholders. Its API is -very similar to UITableView (see the -[Kittens](https://github.com/facebook/AsyncDisplayKit/tree/master/examples/Kittens) -sample project for an example), with some key changes: - -* Rather than setting the table view's `.delegate` and `.dataSource`, you set - its `.asyncDelegate` and `.asyncDataSource`. See - [ASTableView.h](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/ASTableView.h) - for how its delegate and data source protocols differ from UITableView's. - -* Instead of implementing `-tableView:cellForRowAtIndexPath:`, your data - source must implement `-tableView:nodeForRowAtIndexPath:`. This method must - be thread-safe and should not implement reuse. Unlike the UITableView - version, it won't be called when the row is about to display. - -* `-tableView:heightForRowAtIndexPath:` has been removed — ASTableView - lets your cell nodes size themselves. This means you no longer have to - manually duplicate or factor out layout and sizing logic for - dynamically-sized UITableViewCells! - -Next up, how to get the most out of ASDK in your app. diff --git a/docs/guide/4-making-the-most-of-asdk.md b/docs/guide/4-making-the-most-of-asdk.md deleted file mode 100644 index f35ad900b4..0000000000 --- a/docs/guide/4-making-the-most-of-asdk.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -layout: docs -title: Making the most of AsyncDisplayKit -permalink: /guide/4/ -prev: guide/3/ -next: guide/5/ ---- - -## A note on optimisation - -AsyncDisplayKit is powerful and flexible, but it is not a panacea. If your app -has a complex image- or text-heavy user interface, ASDK can definitely help -improve its performance — but if you're blocking the main thread on -network requests, you should consider rearchitecting a few things first. :] - -So why is it worthwhile to change the way we do view layout and rendering, -given that UIKit has always been locked to the main thread and performant iOS -apps have been shipping since iPhone's launch? - -### Modern animations - -Until iOS 7, static animations (à la `+[UIView -animateWithDuration:animations:]`) were the standard. The post-skeuomorphism -redesign brought with it highly-interactive, physics-based animations, with -springs joining the ranks of constant animation functions like -`UIViewAnimationOptionCurveEaseInOut`. - -Classic animations aren't actually executed in your app. They're executed -out-of-process, in the high-priority Core Animation render server. Thanks to -pre-emptive multitasking, an app can block its main thread continuously without -causing the animation to drop a single frame. - -Critically, dynamic animations can't be offloaded the same way, and both -[pop](https://github.com/facebook/pop) and UIKit Dynamics execute physics -simulations on your app's main thread. This is because executing arbitrary -code in the render server would introduce unacceptable latency, even if it -could be done securely. - -Physics-based animations are often interactive, letting you start an animation -and interrupt it before it completes. Paper lets you fling objects across the -screen and catch them before they land, or grab a view that's being pulled by a -spring and tear it off. This requires processing touch events and updating -animation targets in realtime — even short delays for inter-process -communication would shatter the illusion. - -(Fun fact: Inertial scrolling is also a physics animation! UIScrollView has -always implemented its animations on the main thread, which is why stuttery -scrolling is the hallmark of a slow app.) - -### The main-thread bottleneck - -Physics animations aren't the only thing that need to happen on the main -thread. The main thread's [run -loop](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/multithreading/runloopmanagement/runloopmanagement.html) -is responsible for handling touch events and initiating drawing operations -— and with UIKit in the mix, it also has to render text, decode images, -and do any other custom drawing (e.g., using Core Graphics). - -If an iteration of the main thread's run loop takes too long, it will drop an -animation frame and may fail to handle touch events in time. Each iteration of -the run loop must complete within 16ms in order to drive 60fps animations, and -your own code typically has less than 10ms to execute. This means that the -best way to keep your app smooth and responsive is to do as little work on the -main thread as possible. - -What's more, the main thread only executes on one core! Single-threaded view -hierarchies can't take advantage of the multicore CPUs in all modern iOS -devices. This is important for more than just performance reasons — it's -also critical for battery life. Running the CPU on all cores for a short time -is preferable to running one core for an extended amount of time: if the -processor can *race to sleep* by finishing its work and idling faster, it can -spend more time in a low-power mode, improving battery life. - -## When to go asynchronous - -AsyncDisplayKit really shines when used fully asynchronously, shifting both -measurement and rendering passes off the main thread and onto multiple cores. -This requires a completely node-based hierarchy. Just as degrading from -UIViews to CALayers disables view-specific functionality like touch handling -from that point on, degrading from nodes to views disables async behaviour. - -You don't, however, need to convert your app's entire view hierarchy to nodes. -In fact, you shouldn't! Asynchronously bringing up your app's core UI, like -navigation elements or tab bars, would be a very confusing experience. Those -elements of your apps can still be nodes, but should be fully synchronous to -guarantee a fully-usable interface as quickly as possible. (This is why -UIWindow has no node equivalent.) - -There are two key situations where asynchronous hierarchies excel: - -1. *Parallelisation*. Measuring and rendering UITableViewCells (or your app's - equivalent, e.g., story cards in Paper) are embarrassingly parallel - problems. Table cells typically have a fixed width and variable height - determined by their contents — the argument to `-measure:` for one - cell doesn't depend on any other cells' calculations, so we can enqueue an - arbitrary number of cell measurement passes at once. - -2. *Preloading*. An app with five tabs should synchronously load the first - one so content is ready to go as quickly as possible. Once this is - complete and the CPU is idle, why not asynchronously prepare the other tabs - so the user doesn't have to wait? This is inconvenient with views, but - very easy with nodes. - -Paper's asynchronous rendering starts at the story strip. You should profile -your app and watch how people use it in the wild to decide what combination of -synchrony and asynchrony yields the best user experience. - -## Additional optimisations - -Complex hierarchies — even when rendered asynchronously — can -impose a cost because of the sheer number of views involved. Working around -this can be painful, but AsyncDisplayKit makes it easy! - -* *Layer-backing*. In some cases, you can substantially improve your app's - performance by using layers instead of views. Manually converting - view-based code to layers is laborious due to the difference in APIs. - Worse, if at some point you need to enable touch handling or other - view-specific functionality, you have to manually convert everything back - (and risk regressions!). - - With nodes, converting an entire subtree from views to layers is as simple - as... - - rootNode.layerBacked = YES; - - ...and if you need to go back, it's as simple as deleting one line. We - recommend enabling layer-backing as a matter of course in any custom node - that doesn't need touch handling. - -* *Precompositing*. Flattening an entire view hierarchy into a single layer - also improves performance, but comes with a hit to maintainability and - hierarchy-based reasoning. Nodes can do this for you too! - - rootNode.shouldRasterizeDescendants = YES; - - ...will cause the entire node hierarchy from that point on to be rendered - into one layer. - -Next up: AsyncDisplayKit, under the hood. diff --git a/docs/guide/5-under-the-hood.md b/docs/guide/5-under-the-hood.md deleted file mode 100644 index 01229ec3ff..0000000000 --- a/docs/guide/5-under-the-hood.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -layout: docs -title: Under the hood -permalink: /guide/5/ -prev: guide/4/ ---- - -## Node architecture - -*(Skip to the next section if you're not interested in AsyncDisplayKit implementation details.)* - -We've described nodes as an abstraction over views and layers, and shown how to -interact with the underlying UIViews and CALayers when necessary. Nodes don't -wrap or vend their UIKit counterparts, though — an ASImageNode's `.view` -is not a UIImageView! So how do nodes work? - -**NOTE:** Classes whose names begin with `_` are private. Don't use them -directly! - -Creating a node doesn't create its underlying view-layer pair. This is why you -can create nodes cheaply and on background threads. When you use a UIView or -CALayer property on a node, you're actually interacting with a proxy object, -[`_ASPendingState`](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/Private/_ASPendingState.h), -that's preconfigured to match UIView and CALayer defaults. - -The first access to a node's `.view` or `.layer` property causes both to be -initialised and configured with the node's current state. If it has subnodes, -they are recursively loaded as well. Once a node has been loaded, the proxy -object is destroyed and the node becomes main-thread-affined — its -properties will update the underlying view directly. (Layer-backed nodes do -the same, not loading views.) - -Nodes are powered by -[`_ASDisplayLayer`](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/Details/_ASDisplayLayer.h) -and -[`_ASDisplayView`](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/Details/_ASDisplayView.h). -These are lightweight to create and add to their respective hierarchies, and -provide integration points that allow nodes to act as full-fledged views or -layers. It's possible to create nodes that are backed by custom view or layer -classes, but doing so is strongly discouraged as it disables the majority of -ASDK's functionality. - -When Core Animation asks an `_ASDisplayLayer` to draw itself, the request is -forwarded to its node. Unless asynchronous display has been disabled, the -actual draw call won't happen immediately or on the main thread. Instead, a -display block will be added to a background queue. These blocks are executed -in parallel, but you can enable `ASDISPLAYNODE_DELAY_DISPLAY` in -[`ASDisplayNode(AsyncDisplay)`](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/Private/ASDisplayNode%2BAsyncDisplay.mm) -to serialise the render system for debugging. - -Common UIView subclass hooks are forwarded from `_ASDisplayView` to its -underlying node, including touch handling, hit-testing, and gesture recogniser -delegate calls. Because an `_ASDisplayView`'s layer is an `_ASDisplayLayer`, -view-backed nodes also participate in asynchronous display. - -## In practice - -What does this mean for your custom nodes? - -You can implement methods like `-touchesBegan:withEvent:` / -`touchesMoved:withEvent:` / `touchesEnded:withEvent:` / -`touchesCancelled:withEvent:` in your nodes exactly as you would in a UIView -subclass. If you find you need a subclass hook that hasn't already been -provided, please file an issue on GitHub — or add it yourself and submit a -pull request! - -If you need to interact or configure your node's underlying view or layer, -don't do so in `-init`. Instead, override `-didLoad` and check if you're -layer-backed: - -```objective-c -- (void)didLoad -{ - [super didLoad]; - - // add a gesture recogniser, if we have a view to add it to - if (!self.layerBacked) { - _gestureRecogniser = [[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(_tap:)]; - [self.view addGestureRecognizer:_gestureRecogniser]; - } -} -``` - -## *fin.* - -Thanks for reading! If you have any questions, please file a GitHub issue or -post in the [Facebook group](https://www.facebook.com/groups/551597518288687). -We'd love to hear from you. diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index ff8065921a..0000000000 --- a/docs/index.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -layout: page -title: Smooth asynchronous user interfaces for iOS apps ---- - -![logo]({{ site.baseurl }}/assets/logo.png) - -AsyncDisplayKit is an iOS framework that keeps even the most complex user -interfaces smooth and responsive. It was originally built to make Facebook's -[Paper](https://facebook.com/paper) possible, and goes hand-in-hand with -[pop](https://github.com/facebook/pop)'s physics-based animations — but -it's just as powerful with UIKit Dynamics and conventional app designs. - - -
-### Quick start - -ASDK is available on [CocoaPods](http://cocoapods.org). Add the following to your Podfile: - -```ruby -pod 'AsyncDisplayKit' -``` - -(ASDK can also be used as a regular static library: Copy the project to your -codebase manually, adding `AsyncDisplayKit.xcodeproj` to your workspace. Add -`libAsyncDisplayKit.a`, AssetsLibrary, and Photos to the "Link Binary With -Libraries" build phase. Include `-lc++ -ObjC` in your project linker flags.) - -Import the framework header, or create an [Objective-C bridging -header](https://developer.apple.com/library/ios/documentation/swift/conceptual/buildingcocoaapps/MixandMatch.html) -if you're using Swift: - -```objective-c -#import -``` - -AsyncDisplayKit Nodes are a thread-safe abstraction layer over UIViews and -CALayers: - -![logo]({{ site.baseurl }}/assets/node-view-layer.png) - -You can construct entire node hierarchies in parallel, or instantiate and size -a single node on a background thread — for example, you could do -something like this in a UIViewController: - -```objective-c -dispatch_async(_backgroundQueue, ^{ - ASTextNode *node = [[ASTextNode alloc] init]; - node.attributedString = [[NSAttributedString alloc] initWithString:@"hello!" - attributes:nil]; - [node measure:CGSizeMake(screenWidth, FLT_MAX)]; - node.frame = (CGRect){ CGPointZero, node.calculatedSize }; - - // self.view isn't a node, so we can only use it on the main thread - dispatch_async(dispatch_get_main_queue(), ^{ - [self.view addSubview:node.view]; - }); -}); -``` - -AsyncDisplayKit at a glance: - -* `ASImageNode` and `ASTextNode` are drop-in replacements for UIImageView and - UITextView. -* `ASMultiplexImageNode` can load and display progressively higher-quality - variants of an image over a slow cell network, letting you quickly show a - low-resolution photo while the full size downloads. -* `ASNetworkImageNode` is a simpler, single-image counterpart to the Multiplex - node. -* `ASTableView` and `ASCollectionView` are a node-aware UITableView and - UICollectionView, respectively, that can asynchronously preload cell nodes - — from loading network data to rendering — all without blocking - the main thread. - -You can also easily [create your own -nodes](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/ASDisplayNode%2BSubclasses.h) -to implement node hierarchies or custom drawing. - - -
-### Learn more - -* Read the [Getting Started guide]({{ site.baseurl }}/guide) -* Get the [sample projects](https://github.com/facebook/AsyncDisplayKit/tree/master/examples) -* Browse the [API reference]({{ site.baseurl }}/appledoc) -* Watch the [NSLondon talk](http://vimeo.com/103589245) or the [NSSpain talk](https://www.youtube.com/watch?v=RY_X7l1g79Q)