Repository: konoma/fps-counter Branch: master Commit: 0f96db18a052 Files: 62 Total size: 218.4 KB Directory structure: gitextract_5vekfhj0/ ├── .gitignore ├── .jazzy.yaml ├── .swift-version ├── .swiftlint.yml ├── .travis.yml ├── Documentation/ │ ├── Classes/ │ │ └── FPSCounter.html │ ├── Classes.html │ ├── Protocols/ │ │ └── FPSCounterDelegate.html │ ├── Protocols.html │ ├── css/ │ │ ├── highlight.css │ │ └── jazzy.css │ ├── docsets/ │ │ ├── .docset/ │ │ │ └── Contents/ │ │ │ ├── Info.plist │ │ │ └── Resources/ │ │ │ ├── Documents/ │ │ │ │ ├── Classes/ │ │ │ │ │ └── FPSCounter.html │ │ │ │ ├── Classes.html │ │ │ │ ├── Protocols/ │ │ │ │ │ └── FPSCounterDelegate.html │ │ │ │ ├── Protocols.html │ │ │ │ ├── css/ │ │ │ │ │ ├── highlight.css │ │ │ │ │ └── jazzy.css │ │ │ │ ├── index.html │ │ │ │ ├── js/ │ │ │ │ │ └── jazzy.js │ │ │ │ └── undocumented.txt │ │ │ └── docSet.dsidx │ │ ├── .tgz │ │ ├── FPSCounter.docset/ │ │ │ └── Contents/ │ │ │ ├── Info.plist │ │ │ └── Resources/ │ │ │ ├── Documents/ │ │ │ │ ├── Classes/ │ │ │ │ │ └── FPSCounter.html │ │ │ │ ├── Classes.html │ │ │ │ ├── Protocols/ │ │ │ │ │ └── FPSCounterDelegate.html │ │ │ │ ├── Protocols.html │ │ │ │ ├── css/ │ │ │ │ │ ├── highlight.css │ │ │ │ │ └── jazzy.css │ │ │ │ ├── index.html │ │ │ │ ├── js/ │ │ │ │ │ └── jazzy.js │ │ │ │ ├── search.json │ │ │ │ ├── undocumented.json │ │ │ │ └── undocumented.txt │ │ │ └── docSet.dsidx │ │ └── FPSCounter.tgz │ ├── index.html │ ├── js/ │ │ └── jazzy.js │ ├── search.json │ ├── undocumented.json │ └── undocumented.txt ├── FPSCounter.podspec ├── FPSCounter.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata/ │ └── xcschemes/ │ ├── FPSCounter.xcscheme │ └── Sample App.xcscheme ├── LICENSE ├── Package.swift ├── Readme.md ├── SampleApp/ │ ├── AppDelegate.swift │ ├── Assets.xcassets/ │ │ └── AppIcon.appiconset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── TableViewController.swift └── Sources/ ├── FPSCounter.h ├── FPSCounter.swift ├── FPSStatusBarViewController.swift ├── FPSStatusBarWindow.swift └── Info.plist ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ FPSCounter.xcodeproj/xcuserdata build .DS_Store /FPSCounter.xcodeproj/project.xcworkspace/xcuserdata ================================================ FILE: .jazzy.yaml ================================================ swift_version: 5.0.0 output: Documentation ================================================ FILE: .swift-version ================================================ 5.0 ================================================ FILE: .swiftlint.yml ================================================ line_length: 140 disabled_rules: - closing_brace - vertical_whitespace included: - Sources ================================================ FILE: .travis.yml ================================================ os: osx osx_image: xcode10.2 language: objective-c before_script: - pod lib lint --allow-warnings - swiftlint script: - xcodebuild -scheme FPSCounter -destination "platform=iOS Simulator,name=iPhone 8,OS=12.0" ================================================ FILE: Documentation/Classes/FPSCounter.html ================================================ FPSCounter Class Reference

FPSCounter Docs (92% documented)

FPSCounter

public class FPSCounter : NSObject

A class that tracks the current FPS of the running application.

FPSCounter uses CADisplayLink updates to count the frames per second drawn. Set the delegate of this class to get notified in certain intervals of the current FPS.

If you just want to see the FPS in the application you can use the FPSCounter.showInStatusBar() convenience method.

  • Create a new FPSCounter.

    To start receiving FPS updates you need to start tracking with the startTracking(inRunLoop:mode:) method.

    Declaration

    Swift

    public override init()
  • Undocumented

    Declaration

    Swift

    deinit
  • The delegate that should receive FPS updates.

    Declaration

    Swift

    public weak var delegate: FPSCounterDelegate?
  • Delay between FPS updates. Longer delays mean more averaged FPS numbers.

    Declaration

    Swift

    @objc
    public var notificationDelay: TimeInterval
  • Start tracking FPS updates.

    You can specify wich runloop to use for tracking, as well as the runloop modes. Usually you’ll want the main runloop (default), and either the common run loop modes (default), or the tracking mode (RunLoop.Mode.tracking).

    When the counter is already tracking, it’s stopped first.

    Declaration

    Swift

    @objc
    public func startTracking(inRunLoop runloop: RunLoop = .main, mode: RunLoop.Mode = .common)

    Parameters

    runloop

    The runloop to start tracking in

    mode

    The mode(s) to track in the runloop

  • Stop tracking FPS updates.

    This method does nothing if the counter is not currently tracking.

    Declaration

    Swift

    @objc
    public func stopTracking()
  • Add a label in the status bar that shows the applications current FPS.

    Note

    Only do this in debug builds. Apple may reject your app if it covers the status bar.

    Declaration

    Swift

    @objc
    class func showInStatusBar(
        application: UIApplication = .shared,
        runloop: RunLoop = .main,
        mode: RunLoop.Mode = .common
    )

    Parameters

    application

    The UIApplication to show the FPS for

    runloop

    The NSRunLoop to use when tracking FPS. Default is the main run loop

    mode

    The run loop mode to use when tracking. Default uses RunLoop.Mode.common

  • Removes the label that shows the current FPS from the status bar.

    Declaration

    Swift

    @objc
    class func hide()
  • Returns wether the FPS counter is currently visible or not.

    Declaration

    Swift

    @objc
    class var isVisible: Bool { get }
================================================ FILE: Documentation/Classes.html ================================================ Classes Reference

FPSCounter Docs (92% documented)

Classes

The following classes are available globally.

  • A class that tracks the current FPS of the running application.

    FPSCounter uses CADisplayLink updates to count the frames per second drawn. Set the delegate of this class to get notified in certain intervals of the current FPS.

    If you just want to see the FPS in the application you can use the FPSCounter.showInStatusBar() convenience method.

    See more

    Declaration

    Swift

    public class FPSCounter : NSObject
================================================ FILE: Documentation/Protocols/FPSCounterDelegate.html ================================================ FPSCounterDelegate Protocol Reference

FPSCounter Docs (92% documented)

FPSCounterDelegate

public protocol FPSCounterDelegate : NSObjectProtocol

The delegate protocol for the FPSCounter class.

Implement this protocol if you want to receive updates from a FPSCounter.

  • Called in regular intervals while the counter is tracking FPS.

    Declaration

    Swift

    func fpsCounter(_ counter: FPSCounter, didUpdateFramesPerSecond fps: Int)

    Parameters

    counter

    The FPSCounter that sent the update

    fps

    The current FPS of the application

================================================ FILE: Documentation/Protocols.html ================================================ Protocols Reference

FPSCounter Docs (92% documented)

Protocols

The following protocols are available globally.

  • The delegate protocol for the FPSCounter class.

    Implement this protocol if you want to receive updates from a FPSCounter.

    See more

    Declaration

    Swift

    public protocol FPSCounterDelegate : NSObjectProtocol
================================================ FILE: Documentation/css/highlight.css ================================================ /* Credit to https://gist.github.com/wataru420/2048287 */ .highlight { /* Comment */ /* Error */ /* Keyword */ /* Operator */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Deleted */ /* Generic.Deleted.Specific */ /* Generic.Emph */ /* Generic.Error */ /* Generic.Heading */ /* Generic.Inserted */ /* Generic.Inserted.Specific */ /* Generic.Output */ /* Generic.Prompt */ /* Generic.Strong */ /* Generic.Subheading */ /* Generic.Traceback */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Number */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Entity */ /* Name.Exception */ /* Name.Function */ /* Name.Namespace */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } .highlight .c { color: #999988; font-style: italic; } .highlight .err { color: #a61717; background-color: #e3d2d2; } .highlight .k { color: #000000; font-weight: bold; } .highlight .o { color: #000000; font-weight: bold; } .highlight .cm { color: #999988; font-style: italic; } .highlight .cp { color: #999999; font-weight: bold; } .highlight .c1 { color: #999988; font-style: italic; } .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } .highlight .gd { color: #000000; background-color: #ffdddd; } .highlight .gd .x { color: #000000; background-color: #ffaaaa; } .highlight .ge { color: #000000; font-style: italic; } .highlight .gr { color: #aa0000; } .highlight .gh { color: #999999; } .highlight .gi { color: #000000; background-color: #ddffdd; } .highlight .gi .x { color: #000000; background-color: #aaffaa; } .highlight .go { color: #888888; } .highlight .gp { color: #555555; } .highlight .gs { font-weight: bold; } .highlight .gu { color: #aaaaaa; } .highlight .gt { color: #aa0000; } .highlight .kc { color: #000000; font-weight: bold; } .highlight .kd { color: #000000; font-weight: bold; } .highlight .kp { color: #000000; font-weight: bold; } .highlight .kr { color: #000000; font-weight: bold; } .highlight .kt { color: #445588; } .highlight .m { color: #009999; } .highlight .s { color: #d14; } .highlight .na { color: #008080; } .highlight .nb { color: #0086B3; } .highlight .nc { color: #445588; font-weight: bold; } .highlight .no { color: #008080; } .highlight .ni { color: #800080; } .highlight .ne { color: #990000; font-weight: bold; } .highlight .nf { color: #990000; } .highlight .nn { color: #555555; } .highlight .nt { color: #000080; } .highlight .nv { color: #008080; } .highlight .ow { color: #000000; font-weight: bold; } .highlight .w { color: #bbbbbb; } .highlight .mf { color: #009999; } .highlight .mh { color: #009999; } .highlight .mi { color: #009999; } .highlight .mo { color: #009999; } .highlight .sb { color: #d14; } .highlight .sc { color: #d14; } .highlight .sd { color: #d14; } .highlight .s2 { color: #d14; } .highlight .se { color: #d14; } .highlight .sh { color: #d14; } .highlight .si { color: #d14; } .highlight .sx { color: #d14; } .highlight .sr { color: #009926; } .highlight .s1 { color: #d14; } .highlight .ss { color: #990073; } .highlight .bp { color: #999999; } .highlight .vc { color: #008080; } .highlight .vg { color: #008080; } .highlight .vi { color: #008080; } .highlight .il { color: #009999; } ================================================ FILE: Documentation/css/jazzy.css ================================================ html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { background: transparent; border: 0; margin: 0; outline: 0; padding: 0; vertical-align: baseline; } body { background-color: #f2f2f2; font-family: Helvetica, freesans, Arial, sans-serif; font-size: 14px; -webkit-font-smoothing: subpixel-antialiased; word-wrap: break-word; } h1, h2, h3 { margin-top: 0.8em; margin-bottom: 0.3em; font-weight: 100; color: black; } h1 { font-size: 2.5em; } h2 { font-size: 2em; border-bottom: 1px solid #e2e2e2; } h4 { font-size: 13px; line-height: 1.5; margin-top: 21px; } h5 { font-size: 1.1em; } h6 { font-size: 1.1em; color: #777; } .section-name { color: gray; display: block; font-family: Helvetica; font-size: 22px; font-weight: 100; margin-bottom: 15px; } pre, code { font: 0.95em Menlo, monospace; color: #777; word-wrap: normal; } p code, li code { background-color: #eee; padding: 2px 4px; border-radius: 4px; } a { color: #0088cc; text-decoration: none; } ul { padding-left: 15px; } li { line-height: 1.8em; } img { max-width: 100%; } blockquote { margin-left: 0; padding: 0 10px; border-left: 4px solid #ccc; } .content-wrapper { margin: 0 auto; width: 980px; } header { font-size: 0.85em; line-height: 26px; background-color: #414141; position: fixed; width: 100%; z-index: 1; } header img { padding-right: 6px; vertical-align: -4px; height: 16px; } header a { color: #fff; } header p { float: left; color: #999; } header .header-right { float: right; margin-left: 16px; } #breadcrumbs { background-color: #f2f2f2; height: 27px; padding-top: 17px; position: fixed; width: 100%; z-index: 1; margin-top: 26px; } #breadcrumbs #carat { height: 10px; margin: 0 5px; } .sidebar { background-color: #f9f9f9; border: 1px solid #e2e2e2; overflow-y: auto; overflow-x: hidden; position: fixed; top: 70px; bottom: 0; width: 230px; word-wrap: normal; } .nav-groups { list-style-type: none; background: #fff; padding-left: 0; } .nav-group-name { border-bottom: 1px solid #e2e2e2; font-size: 1.1em; font-weight: 100; padding: 15px 0 15px 20px; } .nav-group-name > a { color: #333; } .nav-group-tasks { margin-top: 5px; } .nav-group-task { font-size: 0.9em; list-style-type: none; white-space: nowrap; } .nav-group-task a { color: #888; } .main-content { background-color: #fff; border: 1px solid #e2e2e2; margin-left: 246px; position: absolute; overflow: hidden; padding-bottom: 20px; top: 70px; width: 734px; } .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { margin-bottom: 1em; } .main-content p { line-height: 1.8em; } .main-content section .section:first-child { margin-top: 0; padding-top: 0; } .main-content section .task-group-section .task-group:first-of-type { padding-top: 10px; } .main-content section .task-group-section .task-group:first-of-type .section-name { padding-top: 15px; } .main-content section .heading:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .section { padding: 0 25px; } .highlight { background-color: #eee; padding: 10px 12px; border: 1px solid #e2e2e2; border-radius: 4px; overflow-x: auto; } .declaration .highlight { overflow-x: initial; padding: 0 40px 40px 0; margin-bottom: -25px; background-color: transparent; border: none; } .section-name { margin: 0; margin-left: 18px; } .task-group-section { padding-left: 6px; border-top: 1px solid #e2e2e2; } .task-group { padding-top: 0px; } .task-name-container a[name]:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .item { padding-top: 8px; width: 100%; list-style-type: none; } .item a[name]:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .item code { background-color: transparent; padding: 0; } .item .token, .item .direct-link { padding-left: 3px; margin-left: 15px; font-size: 11.9px; } .item .discouraged { text-decoration: line-through; } .item .declaration-note { font-size: .85em; color: gray; font-style: italic; } .pointer-container { border-bottom: 1px solid #e2e2e2; left: -23px; padding-bottom: 13px; position: relative; width: 110%; } .pointer { background: #f9f9f9; border-left: 1px solid #e2e2e2; border-top: 1px solid #e2e2e2; height: 12px; left: 21px; top: -7px; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -o-transform: rotate(45deg); transform: rotate(45deg); position: absolute; width: 12px; } .height-container { display: none; left: -25px; padding: 0 25px; position: relative; width: 100%; overflow: hidden; } .height-container .section { background: #f9f9f9; border-bottom: 1px solid #e2e2e2; left: -25px; position: relative; width: 100%; padding-top: 10px; padding-bottom: 5px; } .aside, .language { padding: 6px 12px; margin: 12px 0; border-left: 5px solid #dddddd; overflow-y: hidden; } .aside .aside-title, .language .aside-title { font-size: 9px; letter-spacing: 2px; text-transform: uppercase; padding-bottom: 0; margin: 0; color: #aaa; -webkit-user-select: none; } .aside p:last-child, .language p:last-child { margin-bottom: 0; } .language { border-left: 5px solid #cde9f4; } .language .aside-title { color: #4b8afb; } .aside-warning, .aside-deprecated, .aside-unavailable { border-left: 5px solid #ff6666; } .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { color: #ff0000; } .graybox { border-collapse: collapse; width: 100%; } .graybox p { margin: 0; word-break: break-word; min-width: 50px; } .graybox td { border: 1px solid #e2e2e2; padding: 5px 25px 5px 10px; vertical-align: middle; } .graybox tr td:first-of-type { text-align: right; padding: 7px; vertical-align: top; word-break: normal; width: 40px; } .slightly-smaller { font-size: 0.9em; } #footer { position: relative; top: 10px; bottom: 0px; margin-left: 25px; } #footer p { margin: 0; color: #aaa; font-size: 0.8em; } html.dash header, html.dash #breadcrumbs, html.dash .sidebar { display: none; } html.dash .main-content { width: 980px; margin-left: 0; border: none; width: 100%; top: 0; padding-bottom: 0; } html.dash .height-container { display: block; } html.dash .item .token { margin-left: 0; } html.dash .content-wrapper { width: auto; } html.dash #footer { position: static; } ================================================ FILE: Documentation/docsets/.docset/Contents/Info.plist ================================================ CFBundleIdentifier com.jazzy. CFBundleName DocSetPlatformFamily jazzy isDashDocset dashIndexFilePath index.html isJavaScriptEnabled DashDocSetFamily dashtoc ================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/Classes/FPSCounter.html ================================================ FPSCounter Class Reference

Docs (100% documented)

FPSCounter

public class FPSCounter: NSObject

A class that tracks the current FPS of the running application.

FPSCounter uses CADisplayLink updates to count the frames per second drawn. Set the delegate of this class to get notified in certain intervals of the current FPS.

If you just want to see the FPS in the application you can use the showInStatusBar(_:) convenience class function.

  • Create a new FPSCounter.

    To start receiving FPS updates you need to start tracking with the startTracking(inRunLoop:mode:) method.

    Declaration

    Swift

    public override init()
  • The delegate that should receive FPS updates.

    Declaration

    Swift

    public weak var delegate: FPSCounterDelegate?
  • Delay between FPS updates. Longer delays mean more averaged FPS numbers.

    Declaration

    Swift

    public var notificationDelay: NSTimeInterval = 1.0
  • Start tracking FPS updates.

    You can specify wich runloop to use for tracking, as well as the runloop modes. Usually you’ll want the main runloop (default), and either the common run loop modes (default), or the tracking mode (UITrackingRunLoopMode).

    When the counter is already tracking, it’s stopped first.

    • Parameters:
      • runloop: The runloop to start tracking in
      • mode: The mode(s) to track in the runloop

    Declaration

    Swift

    public func startTracking(inRunLoop runloop: NSRunLoop = NSRunLoop.mainRunLoop(), mode: String = NSRunLoopCommonModes)

    Parameters

    runloop

    The runloop to start tracking in

    mode

    The mode(s) to track in the runloop

  • Stop tracking FPS updates.

    This method does nothing if the counter is not currently tracking.

    Declaration

    Swift

    public func stopTracking()
  • Add a label in the status bar that shows the applications current FPS.

    Note

    Only do this in debug builds. Apple may reject your app if it covers the status bar.

  • Parameters:

    • application: The UIApplication to show the FPS for
    • runloop: The NSRunLoop to use when tracking FPS or nil (then it uses the main run loop)
    • mode: The run loop mode to use when tracking. If nil it uses NSRunLoopCommonModes
  • Declaration

    Swift

    public class func showInStatusBar(application: UIApplication, runloop: NSRunLoop? = nil, mode: String? = nil)

    Parameters

    application

    The UIApplication to show the FPS for

    runloop

    The NSRunLoop to use when tracking FPS or nil (then it uses the main run loop)

    mode

    The run loop mode to use when tracking. If nil it uses NSRunLoopCommonModes

================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/Classes.html ================================================ Classes Reference

Docs (100% documented)

Classes

The following classes are available globally.

  • A class that tracks the current FPS of the running application.

    FPSCounter uses CADisplayLink updates to count the frames per second drawn. Set the delegate of this class to get notified in certain intervals of the current FPS.

    If you just want to see the FPS in the application you can use the showInStatusBar(_:) convenience class function.

    See more

    Declaration

    Swift

    public class FPSCounter: NSObject
================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/Protocols/FPSCounterDelegate.html ================================================ FPSCounterDelegate Protocol Reference

Docs (100% documented)

FPSCounterDelegate

public protocol FPSCounterDelegate: NSObjectProtocol

The delegate protocol for the FPSCounter class.

Implement this protocol if you want to receive updates from a FPSCounter.

  • Called in regular intervals while the counter is tracking FPS.

    • Parameters:
      • counter: The FPSCounter that sent the update
      • fps: The current FPS of the application

    Declaration

    Swift

    func fpsCounter(counter: FPSCounter, didUpdateFramesPerSecond fps: Int)

    Parameters

    counter

    The FPSCounter that sent the update

    fps

    The current FPS of the application

================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/Protocols.html ================================================ Protocols Reference

Docs (100% documented)

Protocols

The following protocols are available globally.

  • The delegate protocol for the FPSCounter class.

    Implement this protocol if you want to receive updates from a FPSCounter.

    See more

    Declaration

    Swift

    public protocol FPSCounterDelegate: NSObjectProtocol
================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/css/highlight.css ================================================ /* Credit to https://gist.github.com/wataru420/2048287 */ .highlight { /* Comment */ /* Error */ /* Keyword */ /* Operator */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Deleted */ /* Generic.Deleted.Specific */ /* Generic.Emph */ /* Generic.Error */ /* Generic.Heading */ /* Generic.Inserted */ /* Generic.Inserted.Specific */ /* Generic.Output */ /* Generic.Prompt */ /* Generic.Strong */ /* Generic.Subheading */ /* Generic.Traceback */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Number */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Entity */ /* Name.Exception */ /* Name.Function */ /* Name.Namespace */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } .highlight .c { color: #999988; font-style: italic; } .highlight .err { color: #a61717; background-color: #e3d2d2; } .highlight .k { color: #000000; font-weight: bold; } .highlight .o { color: #000000; font-weight: bold; } .highlight .cm { color: #999988; font-style: italic; } .highlight .cp { color: #999999; font-weight: bold; } .highlight .c1 { color: #999988; font-style: italic; } .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } .highlight .gd { color: #000000; background-color: #ffdddd; } .highlight .gd .x { color: #000000; background-color: #ffaaaa; } .highlight .ge { color: #000000; font-style: italic; } .highlight .gr { color: #aa0000; } .highlight .gh { color: #999999; } .highlight .gi { color: #000000; background-color: #ddffdd; } .highlight .gi .x { color: #000000; background-color: #aaffaa; } .highlight .go { color: #888888; } .highlight .gp { color: #555555; } .highlight .gs { font-weight: bold; } .highlight .gu { color: #aaaaaa; } .highlight .gt { color: #aa0000; } .highlight .kc { color: #000000; font-weight: bold; } .highlight .kd { color: #000000; font-weight: bold; } .highlight .kp { color: #000000; font-weight: bold; } .highlight .kr { color: #000000; font-weight: bold; } .highlight .kt { color: #445588; } .highlight .m { color: #009999; } .highlight .s { color: #d14; } .highlight .na { color: #008080; } .highlight .nb { color: #0086B3; } .highlight .nc { color: #445588; font-weight: bold; } .highlight .no { color: #008080; } .highlight .ni { color: #800080; } .highlight .ne { color: #990000; font-weight: bold; } .highlight .nf { color: #990000; } .highlight .nn { color: #555555; } .highlight .nt { color: #000080; } .highlight .nv { color: #008080; } .highlight .ow { color: #000000; font-weight: bold; } .highlight .w { color: #bbbbbb; } .highlight .mf { color: #009999; } .highlight .mh { color: #009999; } .highlight .mi { color: #009999; } .highlight .mo { color: #009999; } .highlight .sb { color: #d14; } .highlight .sc { color: #d14; } .highlight .sd { color: #d14; } .highlight .s2 { color: #d14; } .highlight .se { color: #d14; } .highlight .sh { color: #d14; } .highlight .si { color: #d14; } .highlight .sx { color: #d14; } .highlight .sr { color: #009926; } .highlight .s1 { color: #d14; } .highlight .ss { color: #990073; } .highlight .bp { color: #999999; } .highlight .vc { color: #008080; } .highlight .vg { color: #008080; } .highlight .vi { color: #008080; } .highlight .il { color: #009999; } ================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/css/jazzy.css ================================================ html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { background: transparent; border: 0; margin: 0; outline: 0; padding: 0; vertical-align: baseline; } body { background-color: #f2f2f2; font-family: Helvetica, freesans, Arial, sans-serif; font-size: 14px; -webkit-font-smoothing: subpixel-antialiased; word-wrap: break-word; } h1, h2, h3 { margin-top: 0.8em; margin-bottom: 0.3em; font-weight: 100; color: black; } h1 { font-size: 2.5em; } h2 { font-size: 2em; border-bottom: 1px solid #e2e2e2; } h4 { font-size: 13px; line-height: 1.5; margin-top: 21px; } h5 { font-size: 1.1em; } h6 { font-size: 1.1em; color: #777; } .section-name { color: gray; display: block; font-family: Helvetica; font-size: 22px; font-weight: 100; margin-bottom: 15px; } pre, code { font: 0.95em Menlo, monospace; color: #777; word-wrap: normal; } p code, li code { background-color: #eee; padding: 2px 4px; border-radius: 4px; } a { color: #0088cc; text-decoration: none; } ul { padding-left: 15px; } li { line-height: 1.8em; } img { max-width: 100%; } blockquote { margin-left: 0; padding: 0 10px; border-left: 4px solid #ccc; } .content-wrapper { margin: 0 auto; width: 980px; } header { font-size: 0.85em; line-height: 26px; background-color: #414141; position: fixed; width: 100%; z-index: 1; } header img { padding-right: 6px; vertical-align: -4px; height: 16px; } header a { color: #fff; } header p { float: left; color: #999; } header .header-right { float: right; margin-left: 16px; } #breadcrumbs { background-color: #f2f2f2; height: 27px; padding-top: 17px; position: fixed; width: 100%; z-index: 1; margin-top: 26px; } #breadcrumbs #carat { height: 10px; margin: 0 5px; } .sidebar { background-color: #f9f9f9; border: 1px solid #e2e2e2; overflow-y: auto; overflow-x: hidden; position: fixed; top: 70px; bottom: 0; width: 230px; word-wrap: normal; } .nav-groups { list-style-type: none; background: #fff; padding-left: 0; } .nav-group-name { border-bottom: 1px solid #e2e2e2; font-size: 1.1em; font-weight: 100; padding: 15px 0 15px 20px; } .nav-group-name > a { color: #333; } .nav-group-tasks { margin-top: 5px; } .nav-group-task { font-size: 0.9em; list-style-type: none; } .nav-group-task a { color: #888; } .main-content { background-color: #fff; border: 1px solid #e2e2e2; margin-left: 246px; position: absolute; overflow: hidden; padding-bottom: 60px; top: 70px; width: 734px; } .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { margin-bottom: 1em; } .main-content p { line-height: 1.8em; } .main-content section .section:first-child { margin-top: 0; padding-top: 0; } .main-content section .task-group-section .task-group:first-of-type { padding-top: 10px; } .main-content section .task-group-section .task-group:first-of-type .section-name { padding-top: 15px; } .section { padding: 0 25px; } .highlight { background-color: #eee; padding: 10px 12px; border: 1px solid #e2e2e2; border-radius: 4px; overflow-x: auto; } .declaration .highlight { overflow-x: initial; padding: 0 40px 40px 0; margin-bottom: -25px; background-color: transparent; border: none; } .section-name { margin: 0; margin-left: 18px; } .task-group-section { padding-left: 6px; border-top: 1px solid #e2e2e2; } .task-group { padding-top: 0px; } .task-name-container a[name]:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .item { padding-top: 8px; width: 100%; list-style-type: none; } .item a[name]:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .item code { background-color: transparent; padding: 0; } .item .token { padding-left: 3px; margin-left: 15px; font-size: 11.9px; } .item .declaration-note { font-size: .85em; color: gray; font-style: italic; } .pointer-container { border-bottom: 1px solid #e2e2e2; left: -23px; padding-bottom: 13px; position: relative; width: 110%; } .pointer { background: #f9f9f9; border-left: 1px solid #e2e2e2; border-top: 1px solid #e2e2e2; height: 12px; left: 21px; top: -7px; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -o-transform: rotate(45deg); transform: rotate(45deg); position: absolute; width: 12px; } .height-container { display: none; left: -25px; padding: 0 25px; position: relative; width: 100%; overflow: hidden; } .height-container .section { background: #f9f9f9; border-bottom: 1px solid #e2e2e2; left: -25px; position: relative; width: 100%; padding-top: 10px; padding-bottom: 5px; } .aside, .language { padding: 6px 12px; margin: 12px 0; border-left: 5px solid #dddddd; overflow-y: hidden; } .aside .aside-title, .language .aside-title { font-size: 9px; letter-spacing: 2px; text-transform: uppercase; padding-bottom: 0; margin: 0; color: #aaa; -webkit-user-select: none; } .aside p:last-child, .language p:last-child { margin-bottom: 0; } .language { border-left: 5px solid #cde9f4; } .language .aside-title { color: #4b8afb; } .aside-warning { border-left: 5px solid #ff6666; } .aside-warning .aside-title { color: #ff0000; } .graybox { border-collapse: collapse; width: 100%; } .graybox p { margin: 0; word-break: break-word; min-width: 50px; } .graybox td { border: 1px solid #e2e2e2; padding: 5px 25px 5px 10px; vertical-align: middle; } .graybox tr td:first-of-type { text-align: right; padding: 7px; vertical-align: top; word-break: normal; width: 40px; } .slightly-smaller { font-size: 0.9em; } #footer { position: absolute; bottom: 10px; margin-left: 25px; } #footer p { margin: 0; color: #aaa; font-size: 0.8em; } html.dash header, html.dash #breadcrumbs, html.dash .sidebar { display: none; } html.dash .main-content { width: 980px; margin-left: 0; border: none; width: 100%; top: 0; padding-bottom: 0; } html.dash .height-container { display: block; } html.dash .item .token { margin-left: 0; } html.dash .content-wrapper { width: auto; } html.dash #footer { position: static; } ================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/index.html ================================================ Reference

Docs (100% documented)

Authors

================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/js/jazzy.js ================================================ window.jazzy = {'docset': false} if (typeof window.dash != 'undefined') { document.documentElement.className += ' dash' window.jazzy.docset = true } if (navigator.userAgent.match(/xcode/i)) { document.documentElement.className += ' xcode' window.jazzy.docset = true } // On doc load, toggle the URL hash discussion if present $(document).ready(function() { if (!window.jazzy.docset) { var linkToHash = $('a[href="' + window.location.hash +'"]'); linkToHash.trigger("click"); } }); // On token click, toggle its discussion and animate token.marginLeft $(".token").click(function(event) { if (window.jazzy.docset) { return; } var link = $(this); var animationDuration = 300; var tokenOffset = "15px"; var original = link.css('marginLeft') == tokenOffset; link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); $content = link.parent().parent().next(); $content.slideToggle(animationDuration); // Keeps the document from jumping to the hash. var href = $(this).attr('href'); if (history.pushState) { history.pushState({}, '', href); } else { location.hash = href; } event.preventDefault(); }); ================================================ FILE: Documentation/docsets/.docset/Contents/Resources/Documents/undocumented.txt ================================================ ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Info.plist ================================================ CFBundleIdentifier com.jazzy.fpscounter CFBundleName FPSCounter DocSetPlatformFamily fpscounter isDashDocset dashIndexFilePath index.html isJavaScriptEnabled DashDocSetFamily dashtoc ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/Classes/FPSCounter.html ================================================ FPSCounter Class Reference

FPSCounter Docs (92% documented)

FPSCounter

public class FPSCounter : NSObject

A class that tracks the current FPS of the running application.

FPSCounter uses CADisplayLink updates to count the frames per second drawn. Set the delegate of this class to get notified in certain intervals of the current FPS.

If you just want to see the FPS in the application you can use the FPSCounter.showInStatusBar() convenience method.

  • Create a new FPSCounter.

    To start receiving FPS updates you need to start tracking with the startTracking(inRunLoop:mode:) method.

    Declaration

    Swift

    public override init()
  • Undocumented

    Declaration

    Swift

    deinit
  • The delegate that should receive FPS updates.

    Declaration

    Swift

    public weak var delegate: FPSCounterDelegate?
  • Delay between FPS updates. Longer delays mean more averaged FPS numbers.

    Declaration

    Swift

    @objc
    public var notificationDelay: TimeInterval
  • Start tracking FPS updates.

    You can specify wich runloop to use for tracking, as well as the runloop modes. Usually you’ll want the main runloop (default), and either the common run loop modes (default), or the tracking mode (RunLoop.Mode.tracking).

    When the counter is already tracking, it’s stopped first.

    Declaration

    Swift

    @objc
    public func startTracking(inRunLoop runloop: RunLoop = .main, mode: RunLoop.Mode = .common)

    Parameters

    runloop

    The runloop to start tracking in

    mode

    The mode(s) to track in the runloop

  • Stop tracking FPS updates.

    This method does nothing if the counter is not currently tracking.

    Declaration

    Swift

    @objc
    public func stopTracking()
  • Add a label in the status bar that shows the applications current FPS.

    Note

    Only do this in debug builds. Apple may reject your app if it covers the status bar.

    Declaration

    Swift

    @objc
    class func showInStatusBar(
        application: UIApplication = .shared,
        runloop: RunLoop = .main,
        mode: RunLoop.Mode = .common
    )

    Parameters

    application

    The UIApplication to show the FPS for

    runloop

    The NSRunLoop to use when tracking FPS. Default is the main run loop

    mode

    The run loop mode to use when tracking. Default uses RunLoop.Mode.common

  • Removes the label that shows the current FPS from the status bar.

    Declaration

    Swift

    @objc
    class func hide()
  • Returns wether the FPS counter is currently visible or not.

    Declaration

    Swift

    @objc
    class var isVisible: Bool { get }
================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/Classes.html ================================================ Classes Reference

FPSCounter Docs (92% documented)

Classes

The following classes are available globally.

  • A class that tracks the current FPS of the running application.

    FPSCounter uses CADisplayLink updates to count the frames per second drawn. Set the delegate of this class to get notified in certain intervals of the current FPS.

    If you just want to see the FPS in the application you can use the FPSCounter.showInStatusBar() convenience method.

    See more

    Declaration

    Swift

    public class FPSCounter : NSObject
================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/Protocols/FPSCounterDelegate.html ================================================ FPSCounterDelegate Protocol Reference

FPSCounter Docs (92% documented)

FPSCounterDelegate

public protocol FPSCounterDelegate : NSObjectProtocol

The delegate protocol for the FPSCounter class.

Implement this protocol if you want to receive updates from a FPSCounter.

  • Called in regular intervals while the counter is tracking FPS.

    Declaration

    Swift

    func fpsCounter(_ counter: FPSCounter, didUpdateFramesPerSecond fps: Int)

    Parameters

    counter

    The FPSCounter that sent the update

    fps

    The current FPS of the application

================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/Protocols.html ================================================ Protocols Reference

FPSCounter Docs (92% documented)

Protocols

The following protocols are available globally.

  • The delegate protocol for the FPSCounter class.

    Implement this protocol if you want to receive updates from a FPSCounter.

    See more

    Declaration

    Swift

    public protocol FPSCounterDelegate : NSObjectProtocol
================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/css/highlight.css ================================================ /* Credit to https://gist.github.com/wataru420/2048287 */ .highlight { /* Comment */ /* Error */ /* Keyword */ /* Operator */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Deleted */ /* Generic.Deleted.Specific */ /* Generic.Emph */ /* Generic.Error */ /* Generic.Heading */ /* Generic.Inserted */ /* Generic.Inserted.Specific */ /* Generic.Output */ /* Generic.Prompt */ /* Generic.Strong */ /* Generic.Subheading */ /* Generic.Traceback */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Number */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Entity */ /* Name.Exception */ /* Name.Function */ /* Name.Namespace */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } .highlight .c { color: #999988; font-style: italic; } .highlight .err { color: #a61717; background-color: #e3d2d2; } .highlight .k { color: #000000; font-weight: bold; } .highlight .o { color: #000000; font-weight: bold; } .highlight .cm { color: #999988; font-style: italic; } .highlight .cp { color: #999999; font-weight: bold; } .highlight .c1 { color: #999988; font-style: italic; } .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } .highlight .gd { color: #000000; background-color: #ffdddd; } .highlight .gd .x { color: #000000; background-color: #ffaaaa; } .highlight .ge { color: #000000; font-style: italic; } .highlight .gr { color: #aa0000; } .highlight .gh { color: #999999; } .highlight .gi { color: #000000; background-color: #ddffdd; } .highlight .gi .x { color: #000000; background-color: #aaffaa; } .highlight .go { color: #888888; } .highlight .gp { color: #555555; } .highlight .gs { font-weight: bold; } .highlight .gu { color: #aaaaaa; } .highlight .gt { color: #aa0000; } .highlight .kc { color: #000000; font-weight: bold; } .highlight .kd { color: #000000; font-weight: bold; } .highlight .kp { color: #000000; font-weight: bold; } .highlight .kr { color: #000000; font-weight: bold; } .highlight .kt { color: #445588; } .highlight .m { color: #009999; } .highlight .s { color: #d14; } .highlight .na { color: #008080; } .highlight .nb { color: #0086B3; } .highlight .nc { color: #445588; font-weight: bold; } .highlight .no { color: #008080; } .highlight .ni { color: #800080; } .highlight .ne { color: #990000; font-weight: bold; } .highlight .nf { color: #990000; } .highlight .nn { color: #555555; } .highlight .nt { color: #000080; } .highlight .nv { color: #008080; } .highlight .ow { color: #000000; font-weight: bold; } .highlight .w { color: #bbbbbb; } .highlight .mf { color: #009999; } .highlight .mh { color: #009999; } .highlight .mi { color: #009999; } .highlight .mo { color: #009999; } .highlight .sb { color: #d14; } .highlight .sc { color: #d14; } .highlight .sd { color: #d14; } .highlight .s2 { color: #d14; } .highlight .se { color: #d14; } .highlight .sh { color: #d14; } .highlight .si { color: #d14; } .highlight .sx { color: #d14; } .highlight .sr { color: #009926; } .highlight .s1 { color: #d14; } .highlight .ss { color: #990073; } .highlight .bp { color: #999999; } .highlight .vc { color: #008080; } .highlight .vg { color: #008080; } .highlight .vi { color: #008080; } .highlight .il { color: #009999; } ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/css/jazzy.css ================================================ html, body, div, span, h1, h3, h4, p, a, code, em, img, ul, li, table, tbody, tr, td { background: transparent; border: 0; margin: 0; outline: 0; padding: 0; vertical-align: baseline; } body { background-color: #f2f2f2; font-family: Helvetica, freesans, Arial, sans-serif; font-size: 14px; -webkit-font-smoothing: subpixel-antialiased; word-wrap: break-word; } h1, h2, h3 { margin-top: 0.8em; margin-bottom: 0.3em; font-weight: 100; color: black; } h1 { font-size: 2.5em; } h2 { font-size: 2em; border-bottom: 1px solid #e2e2e2; } h4 { font-size: 13px; line-height: 1.5; margin-top: 21px; } h5 { font-size: 1.1em; } h6 { font-size: 1.1em; color: #777; } .section-name { color: gray; display: block; font-family: Helvetica; font-size: 22px; font-weight: 100; margin-bottom: 15px; } pre, code { font: 0.95em Menlo, monospace; color: #777; word-wrap: normal; } p code, li code { background-color: #eee; padding: 2px 4px; border-radius: 4px; } a { color: #0088cc; text-decoration: none; } ul { padding-left: 15px; } li { line-height: 1.8em; } img { max-width: 100%; } blockquote { margin-left: 0; padding: 0 10px; border-left: 4px solid #ccc; } .content-wrapper { margin: 0 auto; width: 980px; } header { font-size: 0.85em; line-height: 26px; background-color: #414141; position: fixed; width: 100%; z-index: 1; } header img { padding-right: 6px; vertical-align: -4px; height: 16px; } header a { color: #fff; } header p { float: left; color: #999; } header .header-right { float: right; margin-left: 16px; } #breadcrumbs { background-color: #f2f2f2; height: 27px; padding-top: 17px; position: fixed; width: 100%; z-index: 1; margin-top: 26px; } #breadcrumbs #carat { height: 10px; margin: 0 5px; } .sidebar { background-color: #f9f9f9; border: 1px solid #e2e2e2; overflow-y: auto; overflow-x: hidden; position: fixed; top: 70px; bottom: 0; width: 230px; word-wrap: normal; } .nav-groups { list-style-type: none; background: #fff; padding-left: 0; } .nav-group-name { border-bottom: 1px solid #e2e2e2; font-size: 1.1em; font-weight: 100; padding: 15px 0 15px 20px; } .nav-group-name > a { color: #333; } .nav-group-tasks { margin-top: 5px; } .nav-group-task { font-size: 0.9em; list-style-type: none; white-space: nowrap; } .nav-group-task a { color: #888; } .main-content { background-color: #fff; border: 1px solid #e2e2e2; margin-left: 246px; position: absolute; overflow: hidden; padding-bottom: 20px; top: 70px; width: 734px; } .main-content p, .main-content a, .main-content code, .main-content em, .main-content ul, .main-content table, .main-content blockquote { margin-bottom: 1em; } .main-content p { line-height: 1.8em; } .main-content section .section:first-child { margin-top: 0; padding-top: 0; } .main-content section .task-group-section .task-group:first-of-type { padding-top: 10px; } .main-content section .task-group-section .task-group:first-of-type .section-name { padding-top: 15px; } .main-content section .heading:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .section { padding: 0 25px; } .highlight { background-color: #eee; padding: 10px 12px; border: 1px solid #e2e2e2; border-radius: 4px; overflow-x: auto; } .declaration .highlight { overflow-x: initial; padding: 0 40px 40px 0; margin-bottom: -25px; background-color: transparent; border: none; } .section-name { margin: 0; margin-left: 18px; } .task-group-section { padding-left: 6px; border-top: 1px solid #e2e2e2; } .task-group { padding-top: 0px; } .task-name-container a[name]:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .item { padding-top: 8px; width: 100%; list-style-type: none; } .item a[name]:before { content: ""; display: block; padding-top: 70px; margin: -70px 0 0; } .item code { background-color: transparent; padding: 0; } .item .token, .item .direct-link { padding-left: 3px; margin-left: 15px; font-size: 11.9px; } .item .discouraged { text-decoration: line-through; } .item .declaration-note { font-size: .85em; color: gray; font-style: italic; } .pointer-container { border-bottom: 1px solid #e2e2e2; left: -23px; padding-bottom: 13px; position: relative; width: 110%; } .pointer { background: #f9f9f9; border-left: 1px solid #e2e2e2; border-top: 1px solid #e2e2e2; height: 12px; left: 21px; top: -7px; -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -o-transform: rotate(45deg); transform: rotate(45deg); position: absolute; width: 12px; } .height-container { display: none; left: -25px; padding: 0 25px; position: relative; width: 100%; overflow: hidden; } .height-container .section { background: #f9f9f9; border-bottom: 1px solid #e2e2e2; left: -25px; position: relative; width: 100%; padding-top: 10px; padding-bottom: 5px; } .aside, .language { padding: 6px 12px; margin: 12px 0; border-left: 5px solid #dddddd; overflow-y: hidden; } .aside .aside-title, .language .aside-title { font-size: 9px; letter-spacing: 2px; text-transform: uppercase; padding-bottom: 0; margin: 0; color: #aaa; -webkit-user-select: none; } .aside p:last-child, .language p:last-child { margin-bottom: 0; } .language { border-left: 5px solid #cde9f4; } .language .aside-title { color: #4b8afb; } .aside-warning, .aside-deprecated, .aside-unavailable { border-left: 5px solid #ff6666; } .aside-warning .aside-title, .aside-deprecated .aside-title, .aside-unavailable .aside-title { color: #ff0000; } .graybox { border-collapse: collapse; width: 100%; } .graybox p { margin: 0; word-break: break-word; min-width: 50px; } .graybox td { border: 1px solid #e2e2e2; padding: 5px 25px 5px 10px; vertical-align: middle; } .graybox tr td:first-of-type { text-align: right; padding: 7px; vertical-align: top; word-break: normal; width: 40px; } .slightly-smaller { font-size: 0.9em; } #footer { position: relative; top: 10px; bottom: 0px; margin-left: 25px; } #footer p { margin: 0; color: #aaa; font-size: 0.8em; } html.dash header, html.dash #breadcrumbs, html.dash .sidebar { display: none; } html.dash .main-content { width: 980px; margin-left: 0; border: none; width: 100%; top: 0; padding-bottom: 0; } html.dash .height-container { display: block; } html.dash .item .token { margin-left: 0; } html.dash .content-wrapper { width: auto; } html.dash #footer { position: static; } ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/index.html ================================================ FPSCounter Reference

FPSCounter Docs (92% documented)

Carthage compatible CocoaPods License MIT

FPSCounter

A small library to measure the frame rate of an iOS Application.

You can display the current frames per second in the status bar with a single line. Or if you’d like more control, you can have your own code notified of FPS changes and display it as needed.

Note: You should only use this for debugging purposes. Especially the status bar overlay may cause Apple to reject your app when reviewed.

Usage

The easiest way to use this library is to add a label to the status bar:

FPSCounter.showInStatusBar()

This will replace the status bar with a label that shows the current frames per second the application manages to draw.

You can remove the label any time later:

FPSCounter.hide()

If you’d like more control on how to display the frames, you can create a private FPSCounter instance and set a delegate

self.fpsCounter = FPSCounter()
self.fpsCounter.delegate = self

To retrieve updates you need to start tracking the FPS:

self.fpsCounter.startTracking()

If necessary you can specify what run loop and run loop mode to use while tracking:

self.fpsCounter.startTracking(inRunLoop: myRunLoop, mode: .tracking)

By default RunLoop.main and RunLoop.Mode.common are used.

When you don’t want to receive further updates, you can stop tracking:

self.fpsCounter.stopTracking()

Installation

Carthage

To install this library via Carthage add the following to your Cartfile:

github "konoma/fps-counter" ~> 4.0

Then run the standard carthage update process.

CocoaPods

To install this library via CocoaPods add the following to your Podfile:

pod 'FPSCounter', '~> 4.0'

Then run the standard pod update process.

License

FPSCounter is released under the MIT License.

================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/js/jazzy.js ================================================ window.jazzy = {'docset': false} if (typeof window.dash != 'undefined') { document.documentElement.className += ' dash' window.jazzy.docset = true } if (navigator.userAgent.match(/xcode/i)) { document.documentElement.className += ' xcode' window.jazzy.docset = true } // On doc load, toggle the URL hash discussion if present $(document).ready(function() { if (!window.jazzy.docset) { var linkToHash = $('a[href="' + window.location.hash +'"]'); linkToHash.trigger("click"); } }); // On token click, toggle its discussion and animate token.marginLeft $(".token").click(function(event) { if (window.jazzy.docset) { return; } var link = $(this); var animationDuration = 300; var tokenOffset = "15px"; var original = link.css('marginLeft') == tokenOffset; link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); $content = link.parent().parent().next(); $content.slideToggle(animationDuration); // Keeps the document from jumping to the hash. var href = $(this).attr('href'); if (history.pushState) { history.pushState({}, '', href); } else { location.hash = href; } event.preventDefault(); }); // Dumb down quotes within code blocks that delimit strings instead of quotations // https://github.com/realm/jazzy/issues/714 $("code q").replaceWith(function () { return ["\"", $(this).contents(), "\""]; }); ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/search.json ================================================ {"Protocols/FPSCounterDelegate.html#/s:10FPSCounter0A8DelegateP10fpsCounter_24didUpdateFramesPerSecondyA2AC_SitF":{"name":"fpsCounter(_:didUpdateFramesPerSecond:)","abstract":"

Called in regular intervals while the counter is tracking FPS.

","parent_name":"FPSCounterDelegate"},"Protocols/FPSCounterDelegate.html":{"name":"FPSCounterDelegate","abstract":"

The delegate protocol for the FPSCounter class.

"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)init":{"name":"init()","abstract":"

Create a new FPSCounter.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)dealloc":{"name":"deinit","abstract":"

Undocumented

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/s:10FPSCounterAAC8delegateAA0A8Delegate_pSgvp":{"name":"delegate","abstract":"

The delegate that should receive FPS updates.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(py)notificationDelay":{"name":"notificationDelay","abstract":"

Delay between FPS updates. Longer delays mean more averaged FPS numbers.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)startTrackingInRunLoop:mode:":{"name":"startTracking(inRunLoop:mode:)","abstract":"

Start tracking FPS updates.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)stopTracking":{"name":"stopTracking()","abstract":"

Stop tracking FPS updates.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@CM@FPSCounter@objc(cs)FPSCounter(cm)showInStatusBarWithApplication:runloop:mode:":{"name":"showInStatusBar(application:runloop:mode:)","abstract":"

Add a label in the status bar that shows the applications current FPS.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@CM@FPSCounter@objc(cs)FPSCounter(cm)hide":{"name":"hide()","abstract":"

Removes the label that shows the current FPS from the status bar.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@CM@FPSCounter@objc(cs)FPSCounter(cpy)isVisible":{"name":"isVisible","abstract":"

Returns wether the FPS counter is currently visible or not.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html":{"name":"FPSCounter","abstract":"

A class that tracks the current FPS of the running application.

"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"}} ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/undocumented.json ================================================ { "warnings": [ ], "source_directory": "/Users/alfonso/Development/fps-counter" } ================================================ FILE: Documentation/docsets/FPSCounter.docset/Contents/Resources/Documents/undocumented.txt ================================================ ================================================ FILE: Documentation/index.html ================================================ FPSCounter Reference

FPSCounter Docs (92% documented)

Carthage compatible CocoaPods License MIT

FPSCounter

A small library to measure the frame rate of an iOS Application.

You can display the current frames per second in the status bar with a single line. Or if you’d like more control, you can have your own code notified of FPS changes and display it as needed.

Note: You should only use this for debugging purposes. Especially the status bar overlay may cause Apple to reject your app when reviewed.

Usage

The easiest way to use this library is to add a label to the status bar:

FPSCounter.showInStatusBar()

This will replace the status bar with a label that shows the current frames per second the application manages to draw.

You can remove the label any time later:

FPSCounter.hide()

If you’d like more control on how to display the frames, you can create a private FPSCounter instance and set a delegate

self.fpsCounter = FPSCounter()
self.fpsCounter.delegate = self

To retrieve updates you need to start tracking the FPS:

self.fpsCounter.startTracking()

If necessary you can specify what run loop and run loop mode to use while tracking:

self.fpsCounter.startTracking(inRunLoop: myRunLoop, mode: .tracking)

By default RunLoop.main and RunLoop.Mode.common are used.

When you don’t want to receive further updates, you can stop tracking:

self.fpsCounter.stopTracking()

Installation

Carthage

To install this library via Carthage add the following to your Cartfile:

github "konoma/fps-counter" ~> 4.0

Then run the standard carthage update process.

CocoaPods

To install this library via CocoaPods add the following to your Podfile:

pod 'FPSCounter', '~> 4.0'

Then run the standard pod update process.

License

FPSCounter is released under the MIT License.

================================================ FILE: Documentation/js/jazzy.js ================================================ window.jazzy = {'docset': false} if (typeof window.dash != 'undefined') { document.documentElement.className += ' dash' window.jazzy.docset = true } if (navigator.userAgent.match(/xcode/i)) { document.documentElement.className += ' xcode' window.jazzy.docset = true } // On doc load, toggle the URL hash discussion if present $(document).ready(function() { if (!window.jazzy.docset) { var linkToHash = $('a[href="' + window.location.hash +'"]'); linkToHash.trigger("click"); } }); // On token click, toggle its discussion and animate token.marginLeft $(".token").click(function(event) { if (window.jazzy.docset) { return; } var link = $(this); var animationDuration = 300; var tokenOffset = "15px"; var original = link.css('marginLeft') == tokenOffset; link.animate({'margin-left':original ? "0px" : tokenOffset}, animationDuration); $content = link.parent().parent().next(); $content.slideToggle(animationDuration); // Keeps the document from jumping to the hash. var href = $(this).attr('href'); if (history.pushState) { history.pushState({}, '', href); } else { location.hash = href; } event.preventDefault(); }); // Dumb down quotes within code blocks that delimit strings instead of quotations // https://github.com/realm/jazzy/issues/714 $("code q").replaceWith(function () { return ["\"", $(this).contents(), "\""]; }); ================================================ FILE: Documentation/search.json ================================================ {"Protocols/FPSCounterDelegate.html#/s:10FPSCounter0A8DelegateP10fpsCounter_24didUpdateFramesPerSecondyA2AC_SitF":{"name":"fpsCounter(_:didUpdateFramesPerSecond:)","abstract":"

Called in regular intervals while the counter is tracking FPS.

","parent_name":"FPSCounterDelegate"},"Protocols/FPSCounterDelegate.html":{"name":"FPSCounterDelegate","abstract":"

The delegate protocol for the FPSCounter class.

"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)init":{"name":"init()","abstract":"

Create a new FPSCounter.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)dealloc":{"name":"deinit","abstract":"

Undocumented

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/s:10FPSCounterAAC8delegateAA0A8Delegate_pSgvp":{"name":"delegate","abstract":"

The delegate that should receive FPS updates.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(py)notificationDelay":{"name":"notificationDelay","abstract":"

Delay between FPS updates. Longer delays mean more averaged FPS numbers.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)startTrackingInRunLoop:mode:":{"name":"startTracking(inRunLoop:mode:)","abstract":"

Start tracking FPS updates.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@M@FPSCounter@objc(cs)FPSCounter(im)stopTracking":{"name":"stopTracking()","abstract":"

Stop tracking FPS updates.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@CM@FPSCounter@objc(cs)FPSCounter(cm)showInStatusBarWithApplication:runloop:mode:":{"name":"showInStatusBar(application:runloop:mode:)","abstract":"

Add a label in the status bar that shows the applications current FPS.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@CM@FPSCounter@objc(cs)FPSCounter(cm)hide":{"name":"hide()","abstract":"

Removes the label that shows the current FPS from the status bar.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html#/c:@CM@FPSCounter@objc(cs)FPSCounter(cpy)isVisible":{"name":"isVisible","abstract":"

Returns wether the FPS counter is currently visible or not.

","parent_name":"FPSCounter"},"Classes/FPSCounter.html":{"name":"FPSCounter","abstract":"

A class that tracks the current FPS of the running application.

"},"Classes.html":{"name":"Classes","abstract":"

The following classes are available globally.

"},"Protocols.html":{"name":"Protocols","abstract":"

The following protocols are available globally.

"}} ================================================ FILE: Documentation/undocumented.json ================================================ { "warnings": [ { "file": "/Users/alfonso/Development/fps-counter/Sources/FPSCounter.swift", "line": 71, "symbol": "FPSCounter.deinit", "symbol_kind": "source.lang.swift.decl.function.method.instance", "warning": "undocumented" } ], "source_directory": "/Users/alfonso/Development/fps-counter" } ================================================ FILE: Documentation/undocumented.txt ================================================ ================================================ FILE: FPSCounter.podspec ================================================ Pod::Spec.new do |s| # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.name = "FPSCounter" s.version = "4.1.0" s.homepage = "https://github.com/konoma/fps-counter" s.summary = "A small library to measure the frame rate of an iOS Application." s.description = <<-DESC FPSCounter is a small library to measure the frame rate of an iOS Application. You can display the current frames per second in the status bar with a single line. Or if you'd like more control, you can have your own code notified of FPS changes and display it as needed. DESC # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.license = { :type => "MIT", :file => "LICENSE" } # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.author = { "Markus Gasser" => "markus.gasser@konoma.ch" } # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.platform = :ios, "8.0" # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.source = { :git => "https://github.com/konoma/fps-counter.git", :tag => s.version } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.source_files = "Sources/**/*.{swift,h,m}" s.public_header_files = "Sources/**/*.h" # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.frameworks = "Foundation", "UIKit" # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.requires_arc = true s.swift_version = '5.0' end ================================================ FILE: FPSCounter.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 05371A2F1C88DEEF004C7A44 /* FPSCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 05371A2D1C88DEEF004C7A44 /* FPSCounter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 05371A321C88DFFB004C7A44 /* FPSCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05371A311C88DFFB004C7A44 /* FPSCounter.swift */; }; 05371A3A1C88EA4C004C7A44 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05371A391C88EA4C004C7A44 /* AppDelegate.swift */; }; 05371A3F1C88EA4C004C7A44 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 05371A3D1C88EA4C004C7A44 /* Main.storyboard */; }; 05371A411C88EA4C004C7A44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 05371A401C88EA4C004C7A44 /* Assets.xcassets */; }; 05371A441C88EA4C004C7A44 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 05371A421C88EA4C004C7A44 /* LaunchScreen.storyboard */; }; 05371A4C1C88EB33004C7A44 /* FPSCounter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05371A1F1C88DEA0004C7A44 /* FPSCounter.framework */; }; 05371A4D1C88EB33004C7A44 /* FPSCounter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05371A1F1C88DEA0004C7A44 /* FPSCounter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 05371A501C88EB6F004C7A44 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05371A4F1C88EB6F004C7A44 /* MapKit.framework */; }; 05371A541C88FBCB004C7A44 /* FPSStatusBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05371A531C88FBCB004C7A44 /* FPSStatusBarViewController.swift */; }; 05371A561C8907C0004C7A44 /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05371A511C88F21A004C7A44 /* TableViewController.swift */; }; 05537C3120D4251F0000FC69 /* FPSStatusBarWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05537C3020D4251F0000FC69 /* FPSStatusBarWindow.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 05371A4A1C88EB24004C7A44 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 05371A161C88DEA0004C7A44 /* Project object */; proxyType = 1; remoteGlobalIDString = 05371A1E1C88DEA0004C7A44; remoteInfo = FPSCounter; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 05371A4E1C88EB34004C7A44 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( 05371A4D1C88EB33004C7A44 /* FPSCounter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 05371A1F1C88DEA0004C7A44 /* FPSCounter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FPSCounter.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05371A2D1C88DEEF004C7A44 /* FPSCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FPSCounter.h; sourceTree = ""; }; 05371A2E1C88DEEF004C7A44 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 05371A311C88DFFB004C7A44 /* FPSCounter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FPSCounter.swift; sourceTree = ""; }; 05371A371C88EA4C004C7A44 /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 05371A391C88EA4C004C7A44 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 05371A3E1C88EA4C004C7A44 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 05371A401C88EA4C004C7A44 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 05371A431C88EA4C004C7A44 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 05371A451C88EA4C004C7A44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 05371A4F1C88EB6F004C7A44 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; 05371A511C88F21A004C7A44 /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; 05371A531C88FBCB004C7A44 /* FPSStatusBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FPSStatusBarViewController.swift; sourceTree = ""; }; 05387057207B860900C8F0E9 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; 05387058207B88B500C8F0E9 /* Readme.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Readme.md; sourceTree = ""; }; 05387059207B8CA500C8F0E9 /* FPSCounter.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = FPSCounter.podspec; sourceTree = ""; }; 0538705A207B8DAA00C8F0E9 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 0538705B207B8DAA00C8F0E9 /* .jazzy.yaml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .jazzy.yaml; sourceTree = ""; }; 0538705C207B8DAB00C8F0E9 /* .swift-version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ".swift-version"; sourceTree = ""; }; 05537C3020D4251F0000FC69 /* FPSStatusBarWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FPSStatusBarWindow.swift; sourceTree = ""; }; 3B1885F425542C1A005E0773 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 05371A1B1C88DEA0004C7A44 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 05371A341C88EA4C004C7A44 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 05371A501C88EB6F004C7A44 /* MapKit.framework in Frameworks */, 05371A4C1C88EB33004C7A44 /* FPSCounter.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 05371A151C88DEA0004C7A44 = { isa = PBXGroup; children = ( 3B1885F425542C1A005E0773 /* Package.swift */, 05387058207B88B500C8F0E9 /* Readme.md */, 0538705A207B8DAA00C8F0E9 /* LICENSE */, 05387059207B8CA500C8F0E9 /* FPSCounter.podspec */, 0538705C207B8DAB00C8F0E9 /* .swift-version */, 05387057207B860900C8F0E9 /* .swiftlint.yml */, 0538705B207B8DAA00C8F0E9 /* .jazzy.yaml */, 05371A2C1C88DEEF004C7A44 /* Sources */, 05371A381C88EA4C004C7A44 /* Sample App */, 05371A551C89058A004C7A44 /* Frameworks */, 05371A201C88DEA0004C7A44 /* Products */, ); sourceTree = ""; }; 05371A201C88DEA0004C7A44 /* Products */ = { isa = PBXGroup; children = ( 05371A1F1C88DEA0004C7A44 /* FPSCounter.framework */, 05371A371C88EA4C004C7A44 /* SampleApp.app */, ); name = Products; sourceTree = ""; }; 05371A2C1C88DEEF004C7A44 /* Sources */ = { isa = PBXGroup; children = ( 05371A2E1C88DEEF004C7A44 /* Info.plist */, 05371A2D1C88DEEF004C7A44 /* FPSCounter.h */, 05371A311C88DFFB004C7A44 /* FPSCounter.swift */, 05371A531C88FBCB004C7A44 /* FPSStatusBarViewController.swift */, 05537C3020D4251F0000FC69 /* FPSStatusBarWindow.swift */, ); path = Sources; sourceTree = ""; }; 05371A381C88EA4C004C7A44 /* Sample App */ = { isa = PBXGroup; children = ( 05371A451C88EA4C004C7A44 /* Info.plist */, 05371A401C88EA4C004C7A44 /* Assets.xcassets */, 05371A421C88EA4C004C7A44 /* LaunchScreen.storyboard */, 05371A3D1C88EA4C004C7A44 /* Main.storyboard */, 05371A391C88EA4C004C7A44 /* AppDelegate.swift */, 05371A511C88F21A004C7A44 /* TableViewController.swift */, ); name = "Sample App"; path = SampleApp; sourceTree = ""; }; 05371A551C89058A004C7A44 /* Frameworks */ = { isa = PBXGroup; children = ( 05371A4F1C88EB6F004C7A44 /* MapKit.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 05371A1C1C88DEA0004C7A44 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 05371A2F1C88DEEF004C7A44 /* FPSCounter.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 05371A1E1C88DEA0004C7A44 /* FPSCounter */ = { isa = PBXNativeTarget; buildConfigurationList = 05371A271C88DEA0004C7A44 /* Build configuration list for PBXNativeTarget "FPSCounter" */; buildPhases = ( 05371A571C8A2CAB004C7A44 /* Lint Swift Files */, 05371A1A1C88DEA0004C7A44 /* Sources */, 05371A1B1C88DEA0004C7A44 /* Frameworks */, 05371A1C1C88DEA0004C7A44 /* Headers */, 05371A1D1C88DEA0004C7A44 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = FPSCounter; productName = "fps-counter"; productReference = 05371A1F1C88DEA0004C7A44 /* FPSCounter.framework */; productType = "com.apple.product-type.framework"; }; 05371A361C88EA4C004C7A44 /* SampleApp */ = { isa = PBXNativeTarget; buildConfigurationList = 05371A461C88EA4C004C7A44 /* Build configuration list for PBXNativeTarget "SampleApp" */; buildPhases = ( 05371A331C88EA4C004C7A44 /* Sources */, 05371A341C88EA4C004C7A44 /* Frameworks */, 05371A351C88EA4C004C7A44 /* Resources */, 05371A4E1C88EB34004C7A44 /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( 05371A4B1C88EB24004C7A44 /* PBXTargetDependency */, ); name = SampleApp; productName = "fps-sample-app"; productReference = 05371A371C88EA4C004C7A44 /* SampleApp.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 05371A161C88DEA0004C7A44 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; LastUpgradeCheck = 1020; ORGANIZATIONNAME = "konoma GmbH"; TargetAttributes = { 05371A1E1C88DEA0004C7A44 = { CreatedOnToolsVersion = 7.2.1; LastSwiftMigration = 1020; }; 05371A361C88EA4C004C7A44 = { CreatedOnToolsVersion = 7.2.1; LastSwiftMigration = 1020; }; }; }; buildConfigurationList = 05371A191C88DEA0004C7A44 /* Build configuration list for PBXProject "FPSCounter" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 05371A151C88DEA0004C7A44; productRefGroup = 05371A201C88DEA0004C7A44 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 05371A1E1C88DEA0004C7A44 /* FPSCounter */, 05371A361C88EA4C004C7A44 /* SampleApp */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 05371A1D1C88DEA0004C7A44 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 05371A351C88EA4C004C7A44 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 05371A441C88EA4C004C7A44 /* LaunchScreen.storyboard in Resources */, 05371A411C88EA4C004C7A44 /* Assets.xcassets in Resources */, 05371A3F1C88EA4C004C7A44 /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 05371A571C8A2CAB004C7A44 /* Lint Swift Files */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Lint Swift Files"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 05371A1A1C88DEA0004C7A44 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 05371A541C88FBCB004C7A44 /* FPSStatusBarViewController.swift in Sources */, 05371A321C88DFFB004C7A44 /* FPSCounter.swift in Sources */, 05537C3120D4251F0000FC69 /* FPSStatusBarWindow.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 05371A331C88EA4C004C7A44 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 05371A3A1C88EA4C004C7A44 /* AppDelegate.swift in Sources */, 05371A561C8907C0004C7A44 /* TableViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 05371A4B1C88EB24004C7A44 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 05371A1E1C88DEA0004C7A44 /* FPSCounter */; targetProxy = 05371A4A1C88EB24004C7A44 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ 05371A3D1C88EA4C004C7A44 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 05371A3E1C88EA4C004C7A44 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 05371A421C88EA4C004C7A44 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 05371A431C88EA4C004C7A44 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 05371A251C88DEA0004C7A44 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); 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"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; 05371A261C88DEA0004C7A44 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; 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; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; 05371A281C88DEA0004C7A44 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "ch.konoma.fps-counter"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; name = Debug; }; 05371A291C88DEA0004C7A44 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "ch.konoma.fps-counter"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; }; name = Release; }; 05371A471C88EA4C004C7A44 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; INFOPLIST_FILE = "$(SRCROOT)/SampleApp/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "ch.konoma.fps-sample-app"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; name = Debug; }; 05371A481C88EA4C004C7A44 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; INFOPLIST_FILE = "$(SRCROOT)/SampleApp/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "ch.konoma.fps-sample-app"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 05371A191C88DEA0004C7A44 /* Build configuration list for PBXProject "FPSCounter" */ = { isa = XCConfigurationList; buildConfigurations = ( 05371A251C88DEA0004C7A44 /* Debug */, 05371A261C88DEA0004C7A44 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 05371A271C88DEA0004C7A44 /* Build configuration list for PBXNativeTarget "FPSCounter" */ = { isa = XCConfigurationList; buildConfigurations = ( 05371A281C88DEA0004C7A44 /* Debug */, 05371A291C88DEA0004C7A44 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 05371A461C88EA4C004C7A44 /* Build configuration list for PBXNativeTarget "SampleApp" */ = { isa = XCConfigurationList; buildConfigurations = ( 05371A471C88EA4C004C7A44 /* Debug */, 05371A481C88EA4C004C7A44 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 05371A161C88DEA0004C7A44 /* Project object */; } ================================================ FILE: FPSCounter.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: FPSCounter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: FPSCounter.xcodeproj/xcshareddata/xcschemes/FPSCounter.xcscheme ================================================ ================================================ FILE: FPSCounter.xcodeproj/xcshareddata/xcschemes/Sample App.xcscheme ================================================ ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2016 konoma GmbH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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 THE AUTHORS OR COPYRIGHT HOLDERS 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. ================================================ FILE: Package.swift ================================================ // swift-tools-version:5.3 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "FPSCounter", platforms: [ .iOS(.v10), ], products: [ .library(name: "FPSCounter", targets: ["FPSCounter"]), ], dependencies: [], targets: [ .target(name: "FPSCounter", path: "Sources"), ] ) ================================================ FILE: Readme.md ================================================ > [!WARNING] > This project is not maintained anymore. [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg)](https://github.com/Carthage/Carthage) [![CocoaPods](https://img.shields.io/cocoapods/v/FPSCounter.svg)](https://cocoapods.org/pods/FPSCounter) [![License MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/konoma/fps-counter/blob/master/LICENSE) # FPSCounter A small library to measure the frame rate of an iOS Application. You can display the current frames per second in the status bar with a single line. Or if you'd like more control, you can have your own code notified of FPS changes and display it as needed. _Note_: You should only use this for debugging purposes. Especially the status bar overlay may cause Apple to reject your app when reviewed. ## Usage The easiest way to use this library is to add a label to the status bar: ```swift FPSCounter.showInStatusBar() ``` This will replace the status bar with a label that shows the current frames per second the application manages to draw. You can remove the label any time later: ```swift FPSCounter.hide() ``` If you'd like more control on how to display the frames, you can create a private `FPSCounter` instance and set a delegate ```swift self.fpsCounter = FPSCounter() self.fpsCounter.delegate = self ``` To retrieve updates you need to start tracking the FPS: ```swift self.fpsCounter.startTracking() ``` If necessary you can specify what run loop and run loop mode to use while tracking: ```swift self.fpsCounter.startTracking(inRunLoop: myRunLoop, mode: .tracking) ``` By default `RunLoop.main` and `RunLoop.Mode.common` are used. When you don't want to receive further updates, you can stop tracking: ```swift self.fpsCounter.stopTracking() ``` ## Installation ### Carthage To install this library via [Carthage](https://github.com/Carthage/Carthage) add the following to your `Cartfile`: ```ogdl github "konoma/fps-counter" ~> 4.1 ``` Then run the standard `carthage update` process. ### CocoaPods To install this library via [CocoaPods](https://cocoapods.org) add the following to your `Podfile`: ```ruby pod 'FPSCounter', '~> 4.1' ``` Then run the standard `pod update` process. ## License FPSCounter is released under the [MIT License](https://github.com/konoma/fps-counter/blob/master/LICENSE). ================================================ FILE: SampleApp/AppDelegate.swift ================================================ // // AppDelegate.swift // SampleApp // // Created by Markus Gasser on 03.03.16. // Copyright © 2016 konoma GmbH. All rights reserved. // import UIKit import FPSCounter @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FPSCounter.showInStatusBar() return true } } ================================================ FILE: SampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: SampleApp/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: SampleApp/Base.lproj/Main.storyboard ================================================ ================================================ FILE: SampleApp/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: SampleApp/TableViewController.swift ================================================ // // TableViewController.swift // fps-counter // // Created by Markus Gasser on 03.03.16. // Copyright © 2016 konoma GmbH. All rights reserved. // import UIKit import FPSCounter class TableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() tableView.contentInset = UIEdgeInsets(top: 20.0, left: 0.0, bottom: 0.0, right: 0.0) } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1000 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "Row \((indexPath as NSIndexPath).row)" // Create some artificial delay // Use the sleep amount to control the FPS // // On the simulator, here's what I get while scrolling: // // 1000: ~60 FPS // 10000: ~20-30 FPS usleep(10000) return cell } } ================================================ FILE: Sources/FPSCounter.h ================================================ // // FPSCounter.h // fps-counter // // Created by Markus Gasser on 03.03.16. // Copyright © 2016 konoma GmbH. All rights reserved. // #import //! Project version number for FPSCounter. FOUNDATION_EXPORT double FPSCounterVersionNumber; //! Project version string for FPSCounter. FOUNDATION_EXPORT const unsigned char FPSCounterVersionString[]; ================================================ FILE: Sources/FPSCounter.swift ================================================ // // FPSCounter.swift // fps-counter // // Created by Markus Gasser on 03.03.16. // Copyright © 2016 konoma GmbH. All rights reserved. // import UIKit import QuartzCore /// A class that tracks the current FPS of the running application. /// /// `FPSCounter` uses `CADisplayLink` updates to count the frames per second drawn. /// Set the delegate of this class to get notified in certain intervals of the /// current FPS. /// /// If you just want to see the FPS in the application you can use the /// `FPSCounter.showInStatusBar()` convenience method. /// public class FPSCounter: NSObject { /// Helper class that relays display link updates to the FPSCounter /// /// This is necessary because CADisplayLink retains its target. Thus /// if the FPSCounter class would be the target of the display link /// it would create a retain cycle. The delegate has a weak reference /// to its parent FPSCounter, thus preventing this. /// internal class DisplayLinkProxy: NSObject { /// A weak ref to the parent FPSCounter instance. @objc weak var parentCounter: FPSCounter? /// Notify the parent FPSCounter of a CADisplayLink update. /// /// This method is automatically called by the CADisplayLink. /// /// - Parameters: /// - displayLink: The display link that updated /// @objc func updateFromDisplayLink(_ displayLink: CADisplayLink) { parentCounter?.updateFromDisplayLink(displayLink) } } // MARK: - Initialization private let displayLink: CADisplayLink private let displayLinkProxy: DisplayLinkProxy /// Create a new FPSCounter. /// /// To start receiving FPS updates you need to start tracking with the /// `startTracking(inRunLoop:mode:)` method. /// public override init() { self.displayLinkProxy = DisplayLinkProxy() self.displayLink = CADisplayLink( target: self.displayLinkProxy, selector: #selector(DisplayLinkProxy.updateFromDisplayLink(_:)) ) super.init() self.displayLinkProxy.parentCounter = self } deinit { self.displayLink.invalidate() } // MARK: - Configuration /// The delegate that should receive FPS updates. public weak var delegate: FPSCounterDelegate? /// Delay between FPS updates. Longer delays mean more averaged FPS numbers. @objc public var notificationDelay: TimeInterval = 1.0 // MARK: - Tracking private var runloop: RunLoop? private var mode: RunLoop.Mode? /// Start tracking FPS updates. /// /// You can specify wich runloop to use for tracking, as well as the runloop modes. /// Usually you'll want the main runloop (default), and either the common run loop modes /// (default), or the tracking mode (`RunLoop.Mode.tracking`). /// /// When the counter is already tracking, it's stopped first. /// /// - Parameters: /// - runloop: The runloop to start tracking in /// - mode: The mode(s) to track in the runloop /// @objc public func startTracking(inRunLoop runloop: RunLoop = .main, mode: RunLoop.Mode = .common) { self.stopTracking() self.runloop = runloop self.mode = mode self.displayLink.add(to: runloop, forMode: mode) } /// Stop tracking FPS updates. /// /// This method does nothing if the counter is not currently tracking. /// @objc public func stopTracking() { guard let runloop = self.runloop, let mode = self.mode else { return } self.displayLink.remove(from: runloop, forMode: mode) self.runloop = nil self.mode = nil } // MARK: - Handling Frame Updates private var lastNotificationTime: CFAbsoluteTime = 0.0 private var numberOfFrames = 0 private func updateFromDisplayLink(_ displayLink: CADisplayLink) { if self.lastNotificationTime == 0.0 { self.lastNotificationTime = CFAbsoluteTimeGetCurrent() return } self.numberOfFrames += 1 let currentTime = CFAbsoluteTimeGetCurrent() let elapsedTime = currentTime - self.lastNotificationTime if elapsedTime >= self.notificationDelay { self.notifyUpdateForElapsedTime(elapsedTime) self.lastNotificationTime = 0.0 self.numberOfFrames = 0 } } private func notifyUpdateForElapsedTime(_ elapsedTime: CFAbsoluteTime) { let fps = Int(round(Double(self.numberOfFrames) / elapsedTime)) self.delegate?.fpsCounter(self, didUpdateFramesPerSecond: fps) } } /// The delegate protocol for the FPSCounter class. /// /// Implement this protocol if you want to receive updates from a `FPSCounter`. /// public protocol FPSCounterDelegate: NSObjectProtocol { /// Called in regular intervals while the counter is tracking FPS. /// /// - Parameters: /// - counter: The FPSCounter that sent the update /// - fps: The current FPS of the application /// func fpsCounter(_ counter: FPSCounter, didUpdateFramesPerSecond fps: Int) } ================================================ FILE: Sources/FPSStatusBarViewController.swift ================================================ // // FPSStatusBarViewController.swift // fps-counter // // Created by Markus Gasser on 04.03.16. // Copyright © 2016 konoma GmbH. All rights reserved. // import UIKit /// A view controller to show a FPS label in the status bar. /// class FPSStatusBarViewController: UIViewController { fileprivate let fpsCounter = FPSCounter() private let label = UILabel() // MARK: - Initialization override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) self.commonInit() } required init?(coder decoder: NSCoder) { super.init(coder: decoder) self.commonInit() } private func commonInit() { NotificationCenter.default.addObserver(self, selector: #selector(FPSStatusBarViewController.updateStatusBarFrame(_:)), name: UIApplication.didChangeStatusBarOrientationNotification, object: nil ) } deinit { NotificationCenter.default.removeObserver(self) } // MARK: - View Lifecycle and Events override func loadView() { self.view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)) let font = UIFont.boldSystemFont(ofSize: 10.0) let rect = self.view.bounds.insetBy(dx: 10.0, dy: 0.0) self.label.frame = CGRect(x: rect.origin.x, y: rect.maxY - font.lineHeight - 1.0, width: rect.width, height: font.lineHeight) self.label.autoresizingMask = [ .flexibleWidth, .flexibleTopMargin ] self.label.font = font self.view.addSubview(self.label) self.fpsCounter.delegate = self } @objc func updateStatusBarFrame(_ notification: Notification) { let application = notification.object as? UIApplication let frame = CGRect(x: 0.0, y: 0.0, width: application?.keyWindow?.bounds.width ?? 0.0, height: 20.0) FPSStatusBarViewController.statusBarWindow.frame = frame } // MARK: - Getting the shared status bar window @objc static var statusBarWindow: UIWindow = { let window = FPStatusBarWindow() window.windowLevel = .statusBar window.rootViewController = FPSStatusBarViewController() return window }() } // MARK: - FPSCounterDelegate extension FPSStatusBarViewController: FPSCounterDelegate { @objc func fpsCounter(_ counter: FPSCounter, didUpdateFramesPerSecond fps: Int) { self.resignKeyWindowIfNeeded() let milliseconds = 1000 / max(fps, 1) self.label.text = "\(fps) FPS (\(milliseconds) milliseconds per frame)" switch fps { case 45...: self.view.backgroundColor = .green self.label.textColor = .black case 35...: self.view.backgroundColor = .orange self.label.textColor = .white default: self.view.backgroundColor = .red self.label.textColor = .white } } private func resignKeyWindowIfNeeded() { // prevent the status bar window from becoming the key window and steal events // from the main application window if FPSStatusBarViewController.statusBarWindow.isKeyWindow { UIApplication.shared.delegate?.window??.makeKey() } } } public extension FPSCounter { // MARK: - Show FPS in the status bar /// Add a label in the status bar that shows the applications current FPS. /// /// - Note: /// Only do this in debug builds. Apple may reject your app if it covers the status bar. /// /// - Parameters: /// - application: The `UIApplication` to show the FPS for /// - runloop: The `NSRunLoop` to use when tracking FPS. Default is the main run loop /// - mode: The run loop mode to use when tracking. Default uses `RunLoop.Mode.common` /// @objc class func showInStatusBar( application: UIApplication = .shared, runloop: RunLoop = .main, mode: RunLoop.Mode = .common ) { let window = FPSStatusBarViewController.statusBarWindow window.frame = application.statusBarFrame window.isHidden = false if let controller = window.rootViewController as? FPSStatusBarViewController { controller.fpsCounter.startTracking( inRunLoop: runloop, mode: mode ) } } /// Removes the label that shows the current FPS from the status bar. /// @objc class func hide() { let window = FPSStatusBarViewController.statusBarWindow if let controller = window.rootViewController as? FPSStatusBarViewController { controller.fpsCounter.stopTracking() window.isHidden = true } } /// Returns wether the FPS counter is currently visible or not. /// @objc class var isVisible: Bool { return !FPSStatusBarViewController.statusBarWindow.isHidden } } ================================================ FILE: Sources/FPSStatusBarWindow.swift ================================================ // // FPSStatusBarWindow.swift // FPSCounter // // Created by Markus Gasser on 15.06.18. // Copyright © 2018 konoma GmbH. All rights reserved. // import UIKit class FPStatusBarWindow: UIWindow { override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { // don't hijack touches from the main window return false } } ================================================ FILE: Sources/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType FMWK CFBundleShortVersionString 4.1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass