APNGKit

repository·master·Indexed 25 days ago

https://github.com/onevcat/apngkit

A high-performance Swift framework for loading and displaying Animated Portable Network Graphics (APNG) on iOS, macOS, and tvOS. It provides high-level abstractions for animation playback, error handling, and lifecycle monitoring via APNGImage and APNGImageView. The library supports installation via Swift Package Manager and CocoaPods.

Tokens
2.1K
Snippets
8
Records
11
Agent score
31%

What's inside APNGKit

  1. Handle APNG decoding and playback errors

    master

    APNGKit provides mechanisms to handle errors during both image creation and animation playback.

    During Image Creation

    If APNGImage fails to initialize, check if the error contains a normalImage to fall back to a static version of the image.

    During Animation Playback

    If specific frames are broken, APNGKit can fall back to the default image. You can monitor these events using:

    • onDecodingFrameError: Triggered when a frame fails to decode.
    • onFallBackToDefaultImage: Triggered when the view successfully falls back to the default image.
    • onFallBackToDefaultImageFailed: Triggered if the fallback attempt also fails.
    // Handling creation errors
    do {
        let image = try APNGImage(named: "image_name")
        imageView.image = image
    } catch {
        if let normalImage = error.apngError?.normalImage {
            imageView.staticImage = normalImage
        } else {
            print("Error: \(error)")
        }
    }
    
    // Monitoring playback errors
    imageView.onDecodingFrameError.delegate(on: self) { (self, error) in
        print("A frame cannot be decoded.")
    }
    
    imageView.onFallBackToDefaultImage.delegate(on: self) { (self, _) in
        print("Fall back to default image.")
    }
  2. Install APNGKit via CocoaPods

    master

    To integrate APNGKit using CocoaPods, add it to your Podfile as shown below. Ensure you use use_frameworks! and specify the version requirement.

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '9.0'
    use_frameworks!
    
    target 'your_app' do
      pod 'APNGKit', '~> 2.0'
    end
  3. Install APNGKit via Swift Package Manager

    master

    The recommended way to install APNGKit is using Swift Package Manager. In Xcode, follow these steps:

    1. Go to File > Swift Packages > Add Package Dependency.
    2. Enter the repository URL: https://github.com/onevcat/APNGKit.git.
    3. Select the dependency rule Up to Next Major with version 2.0.0.
  4. Prevent Xcode from compressing APNG files

    master

    Xcode's default build process compresses PNG files, which can strip the APNG animation data and turn it into a static image. If you see the error CgBI chunk found. It seems that the input image is compressed by Xcode..., you have two options:

    1. Rename the file extension: Change your .png files to .apng. APNGKit will detect and handle this extension seamlessly, and Xcode will not attempt to compress them.
    2. Disable PNG compression: Set COMPRESS_PNG_FILES to NO in your app target's build settings. Note that this affects all PNGs in your project.
  5. Control APNG animation playback

    master

    Animations play automatically by default when an image is assigned to an APNGImageView. To control this behavior, use the autoStartAnimationWhenSetImage property and the startAnimating() method.

    let imageView = APNGImageView(frame: .zero)
    // Disable automatic playback
    imageView.autoStartAnimationWhenSetImage = false
    imageView.image = image
    
    // Start the animation manually
    imageView.startAnimating()
  6. Display an APNG Image with APNGImageView

    master

    To display an animation, use APNGImageView, which is a subclass of UIView (iOS) or NSView (macOS).

    Note for Interface Builder users: Drag a standard UIView or NSView to your canvas (do NOT use UIImageView or NSImageView) and change its class to APNGImageView in the Identity Inspector.

    let image: APNGImage = ... 
    
    // Initialize and add the view
    let imageView = APNGImageView(image: image)
    view.addSubview(imageView)
  7. Load an APNG Image

    master

    Use the APNGImage initializer to load images from various sources. Note that these initializers are throwable and can return an APNGKitError.decoderError if the image is invalid.

    import APNGKit
    
    // Load an APNG image from file in main bundle
    var image = try APNGImage(named: "your_image")
    
    // Load an APNG image from a specific file URL
    if let url = Bundle.main.url(forResource: "your_image", withExtension: "apng") {
        image = try APNGImage(fileURL: url)
    }
    
    // Load an APNG image from raw Data
    let data: Data = ... 
    image = try APNGImage(data: data)
  8. Handle APNG playback lifecycle with delegates

    master

    APNGKit provides delegates to monitor the animation lifecycle, such as when a single loop finishes or when the entire animation is complete.

    • onOnePlayDone: Triggered after each loop (respecting numberOfPlays in APNGImage).
    • onAllPlaysDone: Triggered when the entire animation sequence is finished.
    • onFramesInformationPrepared: Triggered when all frame information is loaded, allowing you to access the full image.duration.
    // Monitor single loop completion
    imageView.onOnePlayDone.delegate(on: self) { (self, count) in
        print("Played: \(count)")
    }
    
    // Monitor total animation completion
    imageView.onAllPlaysDone.delegate(on: self) { (self, _) in
        print("All done.")
    }
    
    // Get full duration once frames are prepared
    let image = try APNGImage(named: "image")
    image.onFramesInformationPrepared.delegate(on: self) { (self, _) in
        switch image.duration {
        case .full(let duration):
            print("Full duration: \(duration)")
        case .partial:
            print("This should not happen.")
        }
    }
  9. Run iOS fastlane actions

    master

    The following fastlane actions are available for iOS development. You can run them using fastlane <action> or bundle exec fastlane <action> if you are using Bundler.

    ### ios test
    ```sh
    [bundle exec] fastlane ios test

    ios test_macOS

    [bundle exec] fastlane ios test_macOS

    ios test_iOS

    [bundle exec] fastlane ios test_iOS

    ios test_tvOS

    [bundle exec] fastlane ios test_tvOS

    ios release

    [bundle exec] fastlane ios release

    ios change_log

    [bundle exec] fastlane ios change_log

    ios lint

    [bundle exec] fastlane ios lint