diff --git a/Demo/Source/EmptyViewController.swift b/Demo/Source/EmptyViewController.swift index ed0877e..92994af 100644 --- a/Demo/Source/EmptyViewController.swift +++ b/Demo/Source/EmptyViewController.swift @@ -4,12 +4,28 @@ import Gifu class EmptyViewController: UIViewController { let imageView = GIFImageView(image: #imageLiteral(resourceName: "mugen.gif")) + lazy var customImageView: CustomAnimatedView = { + return CustomAnimatedView(frame: CGRect(x: 0, y: self.view.frame.height - 200, width: 360, height: 200)) + }() + override func viewDidLoad() { super.viewDidLoad() view.addSubview(imageView) + view.addSubview(customImageView) } override func viewDidAppear(_ animated: Bool) { imageView.animate(withGIFNamed: "mugen") + customImageView.animate(withGIFNamed: "earth") + } +} + +class CustomAnimatedView: UIView, GIFAnimatable { + public lazy var animator: Animator? = { + return Animator(withDelegate: self) + }() + + override public func display(_ layer: CALayer) { + updateImageIfNeeded() } } diff --git a/Demo/Source/Main.storyboard b/Demo/Source/Main.storyboard index 43d6dae..d9d8a9b 100755 --- a/Demo/Source/Main.storyboard +++ b/Demo/Source/Main.storyboard @@ -1,5 +1,5 @@ - + diff --git a/Gifu.xcodeproj/project.pbxproj b/Gifu.xcodeproj/project.pbxproj index a48e8ea..8e882be 100644 --- a/Gifu.xcodeproj/project.pbxproj +++ b/Gifu.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 00B8C75F1A364DCE00C188E7 /* ImageSourceHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00B8C75C1A364DCE00C188E7 /* ImageSourceHelpers.swift */; }; 00B8C7961A3650EE00C188E7 /* Gifu.h in Headers */ = {isa = PBXBuildFile; fileRef = 00B8C7951A3650EE00C188E7 /* Gifu.h */; settings = {ATTRIBUTES = (Public, ); }; }; 00BF42CC1D99A1DC00C6F28D /* GIFAnimatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00BF42CB1D99A1DC00C6F28D /* GIFAnimatable.swift */; }; + 00DD26EE1DA9643800A0F683 /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00DD26ED1DA9643800A0F683 /* UIImageView.swift */; }; EAF49C7F1A3A4DE000B395DF /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF49C7E1A3A4DE000B395DF /* UIImage.swift */; }; EAF49CB11A3B6EEB00B395DF /* AnimatedFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF49CB01A3B6EEB00B395DF /* AnimatedFrame.swift */; }; /* End PBXBuildFile section */ @@ -49,6 +50,7 @@ 00B8C75C1A364DCE00C188E7 /* ImageSourceHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageSourceHelpers.swift; sourceTree = ""; }; 00B8C7951A3650EE00C188E7 /* Gifu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Gifu.h; sourceTree = ""; }; 00BF42CB1D99A1DC00C6F28D /* GIFAnimatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GIFAnimatable.swift; sourceTree = ""; }; + 00DD26ED1DA9643800A0F683 /* UIImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = ""; }; EAF49C7E1A3A4DE000B395DF /* UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = ""; }; EAF49CB01A3B6EEB00B395DF /* AnimatedFrame.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedFrame.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -87,6 +89,7 @@ 007E08431BD95E6200883D0C /* Array.swift */, 009BD1431BBC93C800FC982B /* CGSize.swift */, EAF49C7E1A3A4DE000B395DF /* UIImage.swift */, + 00DD26ED1DA9643800A0F683 /* UIImageView.swift */, ); path = Extensions; sourceTree = ""; @@ -304,6 +307,7 @@ 009BD1441BBC93C800FC982B /* CGSize.swift in Sources */, EAF49CB11A3B6EEB00B395DF /* AnimatedFrame.swift in Sources */, 00B8C75F1A364DCE00C188E7 /* ImageSourceHelpers.swift in Sources */, + 00DD26EE1DA9643800A0F683 /* UIImageView.swift in Sources */, 00978B6C1D9C6D2A00A6575F /* Animator.swift in Sources */, 007E08441BD95E6200883D0C /* Array.swift in Sources */, EAF49C7F1A3A4DE000B395DF /* UIImage.swift in Sources */, diff --git a/Source/Classes/GIFAnimatable.swift b/Source/Classes/GIFAnimatable.swift index f3a92f0..d9e4c15 100644 --- a/Source/Classes/GIFAnimatable.swift +++ b/Source/Classes/GIFAnimatable.swift @@ -4,9 +4,6 @@ public protocol GIFAnimatable: class { /// Responsible for managing the animation frames. var animator: Animator? { get set } - /// Used for displaying the animation frames. - var image: UIImage? { get set } - /// Notifies the instance that it needs display. var layer: CALayer { get } @@ -17,12 +14,21 @@ public protocol GIFAnimatable: class { var contentMode: UIViewContentMode { get set } } -extension GIFAnimatable { + +/// A single-property protocol that animatable classes can optionally conform to. +public protocol ImageContainer { + /// Used for displaying the animation frames. + var image: UIImage? { get set } +} + +extension GIFAnimatable where Self: ImageContainer { /// Returns the intrinsic content size based on the size of the image. public var intrinsicContentSize: CGSize { return image?.size ?? CGSize.zero } +} +extension GIFAnimatable { /// Returns the active frame if available. public var activeFrame: UIImage? { return animator?.activeFrame() @@ -63,7 +69,10 @@ extension GIFAnimatable { /// /// - parameter imageData: GIF image data. public func prepareForAnimation(withGIFData imageData: Data) { - image = UIImage(data: imageData) + if var imageContainer = self as? ImageContainer { + imageContainer.image = UIImage(data: imageData) + } + animator?.prepareForAnimation(withGIFData: imageData, size: frame.size, contentMode: contentMode) } @@ -85,8 +94,11 @@ extension GIFAnimatable { /// Updates the image with a new frame if necessary. public func updateImageIfNeeded() { - let frame = animator?.activeFrame() ?? image - if image != frame { image = frame } + if var imageContainer = self as? ImageContainer { + imageContainer.image = activeFrame ?? imageContainer.image + } else { + layer.contents = activeFrame?.cgImage + } } } diff --git a/Source/Extensions/UIImageView.swift b/Source/Extensions/UIImageView.swift new file mode 100644 index 0000000..1f5dd87 --- /dev/null +++ b/Source/Extensions/UIImageView.swift @@ -0,0 +1,2 @@ +/// Makes `UIImageView` conform to `ImageContainer` +extension UIImageView: ImageContainer {} diff --git a/docs/Classes.html b/docs/Classes.html index b437fae..f3778bd 100644 --- a/docs/Classes.html +++ b/docs/Classes.html @@ -45,6 +45,9 @@ + diff --git a/docs/Classes/Animator.html b/docs/Classes/Animator.html index 3f062b2..520f811 100644 --- a/docs/Classes/Animator.html +++ b/docs/Classes/Animator.html @@ -46,6 +46,9 @@ + diff --git a/docs/Classes/GIFImageView.html b/docs/Classes/GIFImageView.html index 573fd13..7d0d349 100644 --- a/docs/Classes/GIFImageView.html +++ b/docs/Classes/GIFImageView.html @@ -46,6 +46,9 @@ + diff --git a/docs/Protocols.html b/docs/Protocols.html index fdc1829..fc823a7 100644 --- a/docs/Protocols.html +++ b/docs/Protocols.html @@ -45,6 +45,9 @@ + @@ -87,6 +90,34 @@ +
  • +
    + + + + ImageContainer + +
    +
    +
    +
    +
    +
    +

    A single-property protocol that animatable classes can optionally conform to.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol ImageContainer
    + +
    +
    +
    +
    +
  • diff --git a/docs/Protocols/GIFAnimatable.html b/docs/Protocols/GIFAnimatable.html index 055104b..caf7cc3 100644 --- a/docs/Protocols/GIFAnimatable.html +++ b/docs/Protocols/GIFAnimatable.html @@ -46,6 +46,9 @@ + @@ -93,33 +96,6 @@ -
  • -
    - - - - image - -
    -
    -
    -
    -
    -
    -

    Used for displaying the animation frames.

    - -
    -
    -

    Declaration

    -
    -

    Swift

    -
    var image: UIImage?
    - -
    -
    -
    -
    -
  • @@ -208,9 +184,9 @@
  • - + - intrinsicContentSize + intrinsicContentSize Extension method @@ -235,6 +211,10 @@
  • + + +
    +
    • diff --git a/docs/Protocols/ImageContainer.html b/docs/Protocols/ImageContainer.html new file mode 100644 index 0000000..4a79165 --- /dev/null +++ b/docs/Protocols/ImageContainer.html @@ -0,0 +1,111 @@ + + + + ImageContainer Protocol Reference + + + + + + + + + + +
      +
      +

      Gifu Docs (100% documented)

      +

      View on GitHub

      +

      Install in Dash

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      ImageContainer

      +
      +
      +
      public protocol ImageContainer
      + +
      +
      +

      A single-property protocol that animatable classes can optionally conform to.

      + +
      +
      +
      +
        +
      • +
        + + + + image + +
        +
        +
        +
        +
        +
        +

        Used for displaying the animation frames.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        var image: UIImage?
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + +
      +
      + +
      + diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes.html index b437fae..f3778bd 100644 --- a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes.html +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes.html @@ -45,6 +45,9 @@
    • +
    diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/Animator.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/Animator.html index 3f062b2..520f811 100644 --- a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/Animator.html +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/Animator.html @@ -46,6 +46,9 @@ + diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/GIFImageView.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/GIFImageView.html index 573fd13..7d0d349 100644 --- a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/GIFImageView.html +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Classes/GIFImageView.html @@ -46,6 +46,9 @@ + diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols.html index fdc1829..fc823a7 100644 --- a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols.html +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols.html @@ -45,6 +45,9 @@ + @@ -87,6 +90,34 @@
    +
  • +
    + + + + ImageContainer + +
    +
    +
    +
    +
    +
    +

    A single-property protocol that animatable classes can optionally conform to.

    + + See more +
    +
    +

    Declaration

    +
    +

    Swift

    +
    public protocol ImageContainer
    + +
    +
    +
    +
    +
  • diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/GIFAnimatable.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/GIFAnimatable.html index 055104b..caf7cc3 100644 --- a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/GIFAnimatable.html +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/GIFAnimatable.html @@ -46,6 +46,9 @@ + @@ -93,33 +96,6 @@ -
  • -
    - - - - image - -
    -
    -
    -
    -
    -
    -

    Used for displaying the animation frames.

    - -
    -
    -

    Declaration

    -
    -

    Swift

    -
    var image: UIImage?
    - -
    -
    -
    -
    -
  • @@ -208,9 +184,9 @@
  • - + - intrinsicContentSize + intrinsicContentSize Extension method @@ -235,6 +211,10 @@
  • + + +
    +
    • diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/ImageContainer.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/ImageContainer.html new file mode 100644 index 0000000..4a79165 --- /dev/null +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/Protocols/ImageContainer.html @@ -0,0 +1,111 @@ + + + + ImageContainer Protocol Reference + + + + + + + + + + +
      +
      +

      Gifu Docs (100% documented)

      +

      View on GitHub

      +

      Install in Dash

      +
      +
      +
      + +
      +
      + +
      +
      +
      +

      ImageContainer

      +
      +
      +
      public protocol ImageContainer
      + +
      +
      +

      A single-property protocol that animatable classes can optionally conform to.

      + +
      +
      +
      +
        +
      • +
        + + + + image + +
        +
        +
        +
        +
        +
        +

        Used for displaying the animation frames.

        + +
        +
        +

        Declaration

        +
        +

        Swift

        +
        var image: UIImage?
        + +
        +
        +
        +
        +
      • +
      +
      +
      +
      + +
      +
      + +
      + diff --git a/docs/docsets/Gifu.docset/Contents/Resources/Documents/index.html b/docs/docsets/Gifu.docset/Contents/Resources/Documents/index.html index 867f168..3338e27 100644 --- a/docs/docsets/Gifu.docset/Contents/Resources/Documents/index.html +++ b/docs/docsets/Gifu.docset/Contents/Resources/Documents/index.html @@ -45,6 +45,9 @@
    • +
    @@ -53,11 +56,11 @@
    -

    Gifu Logo

    +

    Logo

    GitHub release Travis Carthage compatible Join the chat at https://gitter.im/kaishin/gifu Swift 3.0.x platforms

    -

    Gifu adds protocol-based, performance-aware animated GIF support to UIKit, without forcing you to use a UIImageView subclass. (It’s also a prefecture in Japan).

    +

    Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It’s also a prefecture in Japan).

    Swift 2.3 support is on the swift2.3 branch. This branch will not be getting any future updates.

    Install

    @@ -78,7 +81,7 @@ for up to date installation instructions.

    How It Works

    -

    Gifu does not rely on subclassing UIImageView. The Animator class does the heavy-lifting, while the GIFAnimatable protocol exposes the functionality to the view classes that conform to it, using protocol extensions.

    +

    Gifu does not force you to use a specific subclass of UIImageView. The Animator class does the heavy-lifting, while the GIFAnimatable protocol exposes the functionality to the view classes that conform to it, using protocol extensions.

    The Animator has a FrameStore that only keeps a limited number of frames in-memory, effectively creating a buffer for the animation without consuming all the available memory. This approach makes loading large GIFs a lot more resource-friendly.

    @@ -92,7 +95,7 @@ containing 10 frames, Gifu will load the current frame (red), buffer the next tw
    • Use the built-in GIFImageView subclass.
    • -
    • Make UIImageView or any of its subclasses conform to GIFAnimatable.
    • +
    • Make any class conform to GIFAnimatable. Subclassing UIImageView is the easiest since you get most of the required properties for free.

    GIFImageView

    @@ -121,6 +124,12 @@ containing 10 frames, Gifu will load the current frame (red), buffer the next tw
  • prepareForReuse() to free up resources.
  • updateImageIfNeeded() to update the image property if necessary.
  • + +

    This approach is especially powerful when you want to combine the functionality of different image libraries.

    +
    class MyImageView: OtherImageClass, GIFAnimatable {}
    +
    + +

    Keep in mind that you need to have control over the class implementing GIFAnimatable since you cannot add the stored Animator property in an extension.

    Examples

    The simplest way to get started is initializing a GIFAnimatable class in code or in a storyboard, then calling animate(:) on it.

    diff --git a/docs/docsets/Gifu.docset/Contents/Resources/docSet.dsidx b/docs/docsets/Gifu.docset/Contents/Resources/docSet.dsidx index a09b863..4ca826a 100644 Binary files a/docs/docsets/Gifu.docset/Contents/Resources/docSet.dsidx and b/docs/docsets/Gifu.docset/Contents/Resources/docSet.dsidx differ diff --git a/docs/docsets/Gifu.tgz b/docs/docsets/Gifu.tgz index 1e9207e..9aa4e69 100644 Binary files a/docs/docsets/Gifu.tgz and b/docs/docsets/Gifu.tgz differ diff --git a/docs/index.html b/docs/index.html index 867f168..3338e27 100644 --- a/docs/index.html +++ b/docs/index.html @@ -45,6 +45,9 @@ + @@ -53,11 +56,11 @@
    -

    Gifu Logo

    +

    Logo

    GitHub release Travis Carthage compatible Join the chat at https://gitter.im/kaishin/gifu Swift 3.0.x platforms

    -

    Gifu adds protocol-based, performance-aware animated GIF support to UIKit, without forcing you to use a UIImageView subclass. (It’s also a prefecture in Japan).

    +

    Gifu adds protocol-based, performance-aware animated GIF support to UIKit. (It’s also a prefecture in Japan).

    Swift 2.3 support is on the swift2.3 branch. This branch will not be getting any future updates.

    Install

    @@ -78,7 +81,7 @@ for up to date installation instructions.

    How It Works

    -

    Gifu does not rely on subclassing UIImageView. The Animator class does the heavy-lifting, while the GIFAnimatable protocol exposes the functionality to the view classes that conform to it, using protocol extensions.

    +

    Gifu does not force you to use a specific subclass of UIImageView. The Animator class does the heavy-lifting, while the GIFAnimatable protocol exposes the functionality to the view classes that conform to it, using protocol extensions.

    The Animator has a FrameStore that only keeps a limited number of frames in-memory, effectively creating a buffer for the animation without consuming all the available memory. This approach makes loading large GIFs a lot more resource-friendly.

    @@ -92,7 +95,7 @@ containing 10 frames, Gifu will load the current frame (red), buffer the next tw
    • Use the built-in GIFImageView subclass.
    • -
    • Make UIImageView or any of its subclasses conform to GIFAnimatable.
    • +
    • Make any class conform to GIFAnimatable. Subclassing UIImageView is the easiest since you get most of the required properties for free.

    GIFImageView

    @@ -121,6 +124,12 @@ containing 10 frames, Gifu will load the current frame (red), buffer the next tw
  • prepareForReuse() to free up resources.
  • updateImageIfNeeded() to update the image property if necessary.
  • + +

    This approach is especially powerful when you want to combine the functionality of different image libraries.

    +
    class MyImageView: OtherImageClass, GIFAnimatable {}
    +
    + +

    Keep in mind that you need to have control over the class implementing GIFAnimatable since you cannot add the stored Animator property in an extension.

    Examples

    The simplest way to get started is initializing a GIFAnimatable class in code or in a storyboard, then calling animate(:) on it.