Optimizing UITableViewCell For Fast Scrolling

Overview

DWURecyclingAlert

Your code usually has less than ten milliseconds to run before it causes a frame drop.1

Build Status

Visualize Bad Drawings On The Fly

Injects 4 classes:

  • UITableViewCell
  • UICollectionViewCell
  • UITableViewHeaderFooterView
  • UICollectionReusableView (as footers/headers)

Monitors 6 time sensitive API calls:

  • [UIView drawRect:]
  • tableView:cellForRowAtIndexPath:
  • tableView:viewForHeaderInSection:
  • tableView:viewForFooterInSection:
  • collectionView:cellForItemAtIndexPath:
  • collectionView:viewForSupplementaryElementOfKind:atIndexPath:

Visualizes bad drawing code in 2 ways:

  • Displays non-recycled UIView, CALayer and UIImage objects with bold red bolders.
  • Displays the time it takes to complete each time sensitive API calls, in milliseconds.

Usage

Step 1: Drop DWURecyclingAlert.m into your project, Swift or ObjC.

Step 2: There's no step 2.

(Optionally) Using CocoaPods and manually start the injection:

pod 'DWURecyclingAlert'

Then manually start injection by running the following function anywhere in your project:

void Inject_DWURecyclingAlert();

UI Configuration

It's likely that your project happens to use lots of [UIColor redColor] here and there. Or, maybe you want to localize the millisecond warning string with your team's first language. Take a look at the UI Configuration section and customize them the way you like.

How It Works

Method swizzling and associated objects. You could always read the source.

Disabled in Release By Default

DWURecyclingAlert.m requires the DEBUG macro to compile and run. As a result, it's disabled in Release by default. If you also want to disable it in debug builds, comment out the DWURecyclingAlertEnabled macro at the top of the file.

Misc

  • Whether your cell / header / footer are created by code or by nib/storyboard, DWURecyclingAlert.m has a way to scan it.
  • It's perfectly normal for a cell to have multiple subviews that override drawRect:, if that's the case, DWURecyclingAlert.m will calculate the sum for all the time it takes to go through each drawRect: call.
  • DWURecyclingAlert.m requires iOS 6 or higher to compile.

Example Project

Inside this repo you can find the RecyclingAlert example project.

License

DWURecyclingAlert is released under the MIT license. See LICENSE for details.

1: Facebook AsyncDisplayKit Guide. (http://asyncdisplaykit.org/guide)

Comments
  • Support for UICollectionView headers and footers

    Support for UICollectionView headers and footers

    UICollectionView headers and footers are created by using the [dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:] method. It would be a very useful addition if recycling alerts and timings were displayed for headers and footers.

    opened by graemesi 4
  • move some function into calayer

    move some function into calayer

    Hello @diwu,

    這次的改動比之前的有大一些, 主要是有些散落在外的 function, 應該是可以被歸併到 CALayercategory 裡面, 並在前面都加上 dwu_ 前綴.

    寫了一些簡單的 #pragma mark 分別源碼的功能性.

    剩下一些地方就比較小, 像是

    SEL imageSelector = NSSelectorFromString(@"image");
    

    to

    SEL imageSelector = @selector(image);
    

    少一次轉換, 然後

    id returnValue = ((id ( *)(id, SEL, id, id))objc_msgSend)(_self, targetSelector, arg1, arg2);
    

    to

    UIView *returnView = ((UIView * ( *)(id, SEL, id, id))objc_msgSend)(_self, targetSelector, arg1, arg2);
    

    直接當 UIView 取出來, 則不用再作轉換

    for (CALayer *subview in layer.sublayers)
    

    to

    for (CALayer *sublayer in self.sublayers)
    

    等等之類的小地方. 感謝.

    opened by DaidoujiChen 3
  • It is not working with layer in UIView

    It is not working with layer in UIView

    I try to use this but It cannot render the layer on UIView such as borderColor

    screen shot 2558-06-19 at 11 48 40 pm

    following the figure you will see my 3pt border color on bookmark button has not been rendered.

    opened by macbaszii 3
  • reduce some code

    reduce some code

    Hello @diwu,

    在這次的修改裡面, 把 CALayerDWURecyclingAlert 做了一些修減, 可以整個拿掉 method dwu_increaseDwuRecyclingCountByOne, 直接透過 dwuRecyclingCount++ 來控制變數, 看起來會相對直覺一些.

    opened by DaidoujiChen 1
  • reduce code length, fix some selector using

    reduce code length, fix some selector using

    Hello @diwu,

    這次修改的部分主要的目的, 是想把 generateTimeLabelForUITableViewCellgenerateTimeLabelForUICollectionViewCell 類似的部分, 抽出來做為另外一個 function.

    過程中, 有發現一些點, 感覺上怪怪的, 所以一併做了一些修改, 第一個是

    NSString *selStr = NSStringFromSelector(@selector(setDataSource:));
    SEL selector = NSSelectorFromString(selStr);
    SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"dwu_uicollectionview_%@", selStr]);
    

    這類的寫法, 把同樣的 SELNSString 然後又轉回 SEL, 我們應該可以寫成

    SEL selector = @selector(setDataSource:);
    NSString *selStr = NSStringFromSelector(selector);
    SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"dwu_uitableview_%@", selStr]);
    

    減少一次轉換.

    第二個是, 原先的 code 裡面

    SEL cellForItemSel = NSSelectorFromString(cellForItemSelStr);
    SEL newCellForItemSel = NSSelectorFromString([NSString stringWithFormat:@"dwu_%@", selStr]);
    

    在這邊 newCellForItemSel 應該是由 cellForItemSel 這個 SEL 的延續, 而不是 selStr 的, 這邊的 selStr 指的是更外面的 setDataSource:, 我猜測, 這邊我們想要替換的 SEL 應該是 collectionView:cellForItemAtIndexPath:, 所以把程式碼替換成下面的樣子

    SEL cellForItemSel = @selector(collectionView:cellForItemAtIndexPath:);
    NSString *cellForItemSelStr = NSStringFromSelector(cellForItemSel);
    SEL newCellForItemSel = NSSelectorFromString([NSString stringWithFormat:@"dwu_%@", cellForItemSelStr]);
    

    大致上是這個樣子, 可以互相討論, 謝謝. :)

    opened by DaidoujiChen 1
  • remove duplicate data store

    remove duplicate data store

    Hello @diwu,

    在 trace 紅框出現的邏輯時, 發現在 dwu_recursionHelper2 這個 function 裡面, 有部分可以小幅修改一下,

    第一個是, 我們應該可以只用一個 container 就好. 所以我把 cgImageRefSet 整個拆掉了. 第二個是, 純取 address 的話, 可以用 %p 取代 %@.

    另外一個部分, 當 layer.delegate 被放到 cgImageRefDict 時, 會導致該目標無法被釋放, 但是要改起來的話, 會動到比較多地方, 我暫時就先不動他.

    opened by DaidoujiChen 1
  • Fix broken headings in Markdown files

    Fix broken headings in Markdown files

    GitHub changed the way Markdown headings are parsed, so this change fixes it.

    See bryant1410/readmesfix for more information.

    Tackles bryant1410/readmesfix#1

    opened by bryant1410 0
  • Casts for XCode 10.1 version

    Casts for XCode 10.1 version

    Casts for correct XCode 10.1 build:

    diff --git a/RecyclingAlert/DWURecyclingAlert/DWURecyclingAlert.m b/RecyclingAlert/DWURecyclingAlert/DWURecyclingAlert.m
    index 122336b..8ffcc32 100644
    --- a/RecyclingAlert/DWURecyclingAlert/DWURecyclingAlert.m
    +++ b/RecyclingAlert/DWURecyclingAlert/DWURecyclingAlert.m
    @@ -246,7 +246,7 @@ static void dwu_swizzleDrawRectIfNotYet(CALayer *layer) {
         if (![layer.delegate isKindOfClass:[UIView class]]) {
             return;
         }
    -    UIView *containerView = layer.delegate;
    +    UIView *containerView = (UIView *)layer.delegate;
         if (!dwu_implementsSelector(containerView, @selector(drawRect:))) {
             return;
         }
    @@ -316,7 +316,7 @@ - (void)dwu_scanLayerHierarchyRecursively {
     }
     
     - (UIView *)dwu_findCell {
    -    UIView *containerView = self.delegate;
    +    UIView *containerView = (UIView *) self.delegate;
         if (!containerView) {
             return nil;
         }
    @@ -338,7 +338,7 @@ - (UIView *)dwu_findCell {
     
     - (void)dwu_injectLayer: (CALayer *)layer withCellDelegate:(UIView *)cellDelegate {
         if (layer.delegate && [layer.delegate isKindOfClass:[UIView class]]) {
    -        UIView *containerView = layer.delegate;
    +        UIView *containerView = (UIView *) layer.delegate;
             containerView.dwuCellDelegate = cellDelegate;
         }
     }
    @@ -465,4 +465,4 @@ static void dwu_generateTimeLabelForUICollectionViewCell() {
             dwu_generateTimeLabelForUICollectionViewCell();
         }
     }
    -#endif
    \ No newline at end of file
    +#endif
    
    opened by demensdeum 0
Owner
diwup
Engineering Manager at Indeed.com
diwup
Light wrapper of UITableViewCell that allows extra customization for tvOS

TvOSCustomizableTableViewCell Light wrapper of UITableViewCell that allows extra customization for tvOS If you would like to have the same level of cu

Zattoo 31 Nov 9, 2022
Template auto layout cell for automatically UITableViewCell height calculating

UITableView-FDTemplateLayoutCell Overview Template auto layout cell for automatically UITableViewCell height calculating. Basic usage If you have a se

null 10k Dec 31, 2022
A UITableViewCell with an editable text field

FDTextFieldTableViewCell Features Fully featured like the Right Detail style Adds a UITextField to the cell and places it correctly Usage Select a cel

William Entriken 26 May 30, 2022
An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.

MGSwipeTableCell MGSwipeTableCell is an easy to use UITableViewCell subclass that allows to display swipeable buttons with a variety of transitions. T

Imanol Fernandez 7k Dec 26, 2022
An easy-to-use UITableViewCell subclass that implements a swippable content view which exposes utility buttons (similar to iOS 7 Mail Application)

SWTableViewCell An easy-to-use UITableViewCell subclass that implements a swipeable content view which exposes utility buttons (similar to iOS 7 Mail

Christopher Wendel 7.2k Dec 31, 2022
Convenient UITableViewCell subclass that implements a swippable content to trigger actions (similar to the Mailbox app).

MCSwipeTableViewCell An effort to show how one would implement a UITableViewCell like the one we can see in the very well executed Mailbox iOS app. Pr

Ali Karagoz 3k Dec 16, 2022
Simple timeline view implemented by UITableViewCell

TimelineTableViewCell TimelineTableViewCell is a simple timeline view implemented by UITableViewCell. The UI design of TimelineTableViewCell is inspir

Zheng-Xiang Ke 1.3k Dec 25, 2022
Swipeable UITableViewCell/UICollectionViewCell based on the stock Mail.app, implemented in Swift.

SwipeCellKit Swipeable UITableViewCell/UICollectionViewCell based on the stock Mail.app, implemented in Swift. About A swipeable UITableViewCell or UI

null 6k Jan 7, 2023
Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. [iOS/macOS/tvOS/CALayer]

Extremely Fast views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainabl

layoutBox 2.1k Dec 22, 2022
Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast

Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. [iOS/macOS/tvOS/CALayer]

layoutBox 2.1k Jan 2, 2023
Scrollable UINavigationBar that follows the scrolling of a UIScrollView

A custom UINavigationController that enables the scrolling of the navigation bar alongside the scrolling of an observed content view Versioning notes

Andrea Mazzini 6.1k Dec 24, 2022
A container view that responds to scrolling of UIScrollView

FlexibleHeader A container view that responds to scrolling of UIScrollView. normal threshold FlexibleHeaderExecutantType Getting Started Progressive I

DongHee Kang 69 May 2, 2022
Infinite paging controller, scrolling through contents and title bar scrolls with a delay

PageController PageController is infinite paging controller, scrolling through contents and title bar scrolls with a delay. Then it provide user inter

Hirohisa Kawasaki 408 Nov 28, 2022
List a collection of items in a horizontally scrolling view. A scaling factor controls the size of the items relative to the center.

CAROUSEL List a collection of items in a horizontally scrolling view. A scaling factor controls the size of the items relative to the center. We speci

Ramotion 557 Dec 31, 2022
SwiftUI, peek scrolling animation and card tapped animation, using GeometryReader

SwiftUI, peek scrolling animation and card tapped animation, using GeometryReader, follow the livestream tutorial by MengTo.

Terry Kuo 4 Jun 10, 2022
Give pull-to-refresh & infinite scrolling to any UIScrollView with 1 line of code.

SVPullToRefresh + SVInfiniteScrolling These UIScrollView categories makes it super easy to add pull-to-refresh and infinite scrolling fonctionalities

Sam Vermette 4.9k Dec 1, 2022
ESPullToRefresh is an easy-to-use component that give pull-to-refresh and infinite-scrolling implemention for developers.

ESPullToRefresh is an easy-to-use component that give pull-to-refresh and infinite-scrolling implemention for developers.

Vincent Li 1.7k Jan 8, 2023
Scrolling the image as a background in Swift

Scrolling the image as a background!

Aleksandr Bychkovskiy 0 Nov 7, 2021
Flix is an app the uses the the movies database to get upcoming movies, with infinite scrolling

Flix Flix is an app the uses the the movies database to get upcoming movies, with infinite scrolling Libraries Flix uses Swift Package Manager (SPM),

null 0 Oct 31, 2021
A custom image view that implements device motion scrolling

YXTMotionView A custom image view that implements device motion scrolling Installation CocoaPods Add the dependency to your Podfile: platform :ios pod

Hanton Yang 79 Dec 17, 2022