Skip to content

Commit

Permalink
Adds support for animated gif images (#86)
Browse files Browse the repository at this point in the history
Fixes #76
  • Loading branch information
JanGorman authored May 10, 2018
1 parent fe5010e commit 0191791
Show file tree
Hide file tree
Showing 15 changed files with 236 additions and 36 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "Frameworks/SwiftyGif"]
path = Frameworks/SwiftyGif
url = https://github.com/kirualex/SwiftyGif
6 changes: 4 additions & 2 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ trailing_whitespace:
cyclomatic_complexity:
warning: 15


opt_in_rules:
- attributes
- closure_end_indentation
Expand All @@ -48,4 +47,7 @@ opt_in_rules:
disabled_rules:
- force_cast
- colon
- unused_optional_binding
- unused_optional_binding

excluded:
- Frameworks/SwiftyGif
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ osx_image: xcode9.3
before_script:
- brew update && brew upgrade swiftlint
script:
- git submodule init
- bundle exec danger

6 changes: 4 additions & 2 deletions Agrume.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "Agrume"
s.version = "5.0.1"
s.version = "5.0.2"
s.summary = "An iOS image viewer written in Swift."
s.swift_version = "4.1"

Expand All @@ -20,6 +20,8 @@ Pod::Spec.new do |s|

s.source = { :git => "https://github.com/JanGorman/Agrume.git", :tag => s.version}

s.source_files = "Classes", "Agrume/*.swift"
s.source_files = "Classes", "Agrume/*.swift"

s.dependency "SwiftyGif"

end
76 changes: 76 additions & 0 deletions Agrume.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@
remoteGlobalIDString = F2A51FED1B10E00700924912;
remoteInfo = Agrume;
};
F2D7BA1620A47C6600D5EE66 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = FA29E9321CA9340E00E579D5;
remoteInfo = SwiftyGifExample;
};
F2D7BA1820A47C6600D5EE66 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = FA29E9461CA9340F00E579D5;
remoteInfo = SwiftyGifTests;
};
F2D7BA1A20A47C6600D5EE66 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3B18BAF41E289899009C125A;
remoteInfo = SwiftyGif;
};
F2D7BA1C20A47D1700D5EE66 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 3B18BAF31E289899009C125A;
remoteInfo = SwiftyGif;
};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
Expand All @@ -42,6 +70,7 @@
F2A51FF91B10E00700924912 /* AgrumeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AgrumeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
F2A51FFF1B10E00700924912 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F2A5200A1B10E29B00924912 /* Agrume.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Agrume.swift; sourceTree = "<group>"; };
F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SwiftyGif.xcodeproj; path = Frameworks/SwiftyGif/SwiftyGif.xcodeproj; sourceTree = "<group>"; };
F2D9598B1B1A108800073772 /* AgrumeCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AgrumeCell.swift; sourceTree = "<group>"; };
F2DC79D51B170C4B00818A8C /* ImageDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageDownloader.swift; sourceTree = "<group>"; };
F2EE29AD209F31B800F281A2 /* Foundation+Agrume.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Foundation+Agrume.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -69,6 +98,7 @@
F2A51FE41B10E00700924912 = {
isa = PBXGroup;
children = (
F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */,
F2A51FF01B10E00700924912 /* Agrume */,
F2A51FFD1B10E00700924912 /* AgrumeTests */,
F2A51FEF1B10E00700924912 /* Products */,
Expand Down Expand Up @@ -128,6 +158,16 @@
name = "Supporting Files";
sourceTree = "<group>";
};
F2D7BA1120A47C6600D5EE66 /* Products */ = {
isa = PBXGroup;
children = (
F2D7BA1720A47C6600D5EE66 /* SwiftyGifExample.app */,
F2D7BA1920A47C6600D5EE66 /* SwiftyGifTests.xctest */,
F2D7BA1B20A47C6600D5EE66 /* SwiftyGif.framework */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -155,6 +195,7 @@
buildRules = (
);
dependencies = (
F2D7BA1D20A47D1700D5EE66 /* PBXTargetDependency */,
);
name = Agrume;
productName = Agrume;
Expand Down Expand Up @@ -210,6 +251,12 @@
mainGroup = F2A51FE41B10E00700924912;
productRefGroup = F2A51FEF1B10E00700924912 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = F2D7BA1120A47C6600D5EE66 /* Products */;
ProjectRef = F2D7BA1020A47C6600D5EE66 /* SwiftyGif.xcodeproj */;
},
);
projectRoot = "";
targets = (
F2A51FED1B10E00700924912 /* Agrume */,
Expand All @@ -218,6 +265,30 @@
};
/* End PBXProject section */

/* Begin PBXReferenceProxy section */
F2D7BA1720A47C6600D5EE66 /* SwiftyGifExample.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = SwiftyGifExample.app;
remoteRef = F2D7BA1620A47C6600D5EE66 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
F2D7BA1920A47C6600D5EE66 /* SwiftyGifTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = SwiftyGifTests.xctest;
remoteRef = F2D7BA1820A47C6600D5EE66 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
F2D7BA1B20A47C6600D5EE66 /* SwiftyGif.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = SwiftyGif.framework;
remoteRef = F2D7BA1A20A47C6600D5EE66 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */

/* Begin PBXResourcesBuildPhase section */
F2A51FEC1B10E00700924912 /* Resources */ = {
isa = PBXResourcesBuildPhase;
Expand Down Expand Up @@ -284,6 +355,11 @@
target = F2A51FED1B10E00700924912 /* Agrume */;
targetProxy = F2A51FFB1B10E00700924912 /* PBXContainerItemProxy */;
};
F2D7BA1D20A47D1700D5EE66 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = SwiftyGif;
targetProxy = F2D7BA1C20A47D1700D5EE66 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */

/* Begin XCBuildConfiguration section */
Expand Down
15 changes: 6 additions & 9 deletions Agrume/Agrume.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ public final class Agrume: UIViewController {
/// Hide status bar when presenting. Defaults to `false`
public var hideStatusBar = false

/// Tap behaviour, i.e. what happens when you tap outside of the image area
public enum TapBehavior {
case dismissIfZoomedOut
case dismissAlways
case zoomOut
}
/// Default tap behaviour is to dismiss the view if zoomed out
public var tapBehavior: TapBehavior = .dismissIfZoomedOut

/// Initialize with a single image
Expand Down Expand Up @@ -177,6 +179,10 @@ public final class Agrume: UIViewController {
}

private var downloadTask: URLSessionDataTask?

public override var preferredStatusBarStyle: UIStatusBarStyle {
return statusBarStyle ?? super.preferredStatusBarStyle
}

/// Present Agrume
/// - Parameter viewController: The UIViewController to present from
Expand Down Expand Up @@ -365,12 +371,3 @@ extension Agrume: AgrumeCellDelegate {
return dataSource?.numberOfImages == 1
}
}

extension Agrume {

// MARK: Status Bar

public override var preferredStatusBarStyle: UIStatusBarStyle {
return statusBarStyle ?? super.preferredStatusBarStyle
}
}
7 changes: 6 additions & 1 deletion Agrume/AgrumeCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//

import UIKit
import SwiftyGif

protocol AgrumeCellDelegate: AnyObject {

Expand Down Expand Up @@ -39,7 +40,11 @@ final class AgrumeCell: UICollectionViewCell {

var image: UIImage? {
didSet {
imageView.image = image
if image?.imageData != nil, let image = image {
imageView.setGifImage(image)
} else {
imageView.image = image
}
updateScrollViewAndImageViewForCurrentMetrics()
}
}
Expand Down
29 changes: 23 additions & 6 deletions Agrume/ImageDownloader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
//

import UIKit
import ImageIO
import MobileCoreServices
import SwiftyGif

final class ImageDownloader {

static func downloadImage(_ url: URL, completion: @escaping (_ image: UIImage?) -> Void) -> URLSessionDataTask? {
var configuration = URLSessionConfiguration.default
if #available(iOS 11.0, *) {
configuration.waitsForConnectivity = true
}
let session = URLSession(configuration: configuration)
let session = URLSession(configuration: newConfiguration())
let task = session.dataTask(with: url) { data, _, error in
var image: UIImage?
defer {
Expand All @@ -20,10 +19,28 @@ final class ImageDownloader {
}
}
guard let data = data, error == nil else { return }
image = UIImage(data: data)
if isAnimatedImage(data) {
image = UIImage(gifData: data)
} else {
image = UIImage(data: data)
}
}
task.resume()
return task
}

private static func newConfiguration() -> URLSessionConfiguration {
var configuration = URLSessionConfiguration.default
if #available(iOS 11.0, *) {
configuration.waitsForConnectivity = true
}
return configuration
}

private static func isAnimatedImage(_ data: Data) -> Bool {
guard let imageSource = CGImageSourceCreateWithData(data as CFData, nil),
let imageType = CGImageSourceGetType(imageSource) else { return false }
return UTTypeConformsTo(imageType, kUTTypeGIF)
}

}
1 change: 1 addition & 0 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github "kirualex/SwiftyGif"
8 changes: 8 additions & 0 deletions Example/Agrume Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
F2A520201B130C7E00924912 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F2A5201E1B130C7E00924912 /* Main.storyboard */; };
F2A520221B130C7E00924912 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F2A520211B130C7E00924912 /* Images.xcassets */; };
F2A520251B130C7E00924912 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = F2A520231B130C7E00924912 /* LaunchScreen.xib */; };
F2D7BA1F20A47FB500D5EE66 /* AnimatedGifViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D7BA1E20A47FB500D5EE66 /* AnimatedGifViewController.swift */; };
F2D7BA2220A4812C00D5EE66 /* animated.gif in Resources */ = {isa = PBXBuildFile; fileRef = F2D7BA2120A4812C00D5EE66 /* animated.gif */; };
F2D9598E1B1A133800073772 /* SingleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D9598D1B1A133800073772 /* SingleImageViewController.swift */; };
F2D959911B1A140200073772 /* SingleURLViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D959901B1A140200073772 /* SingleURLViewController.swift */; };
F2D959931B1A153F00073772 /* MultipleImagesCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2D959921B1A153F00073772 /* MultipleImagesCollectionViewController.swift */; };
Expand Down Expand Up @@ -66,6 +68,8 @@
F2A5202A1B130C7E00924912 /* Agrume ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Agrume ExampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
F2A5202F1B130C7E00924912 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F2A5203A1B130CC000924912 /* Agrume.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Agrume.xcodeproj; path = ../Agrume.xcodeproj; sourceTree = "<group>"; };
F2D7BA1E20A47FB500D5EE66 /* AnimatedGifViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedGifViewController.swift; sourceTree = "<group>"; };
F2D7BA2120A4812C00D5EE66 /* animated.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = animated.gif; sourceTree = "<group>"; };
F2D9598D1B1A133800073772 /* SingleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleImageViewController.swift; sourceTree = "<group>"; };
F2D959901B1A140200073772 /* SingleURLViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleURLViewController.swift; sourceTree = "<group>"; };
F2D959921B1A153F00073772 /* MultipleImagesCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultipleImagesCollectionViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -116,6 +120,8 @@
F2A520171B130C7E00924912 /* Agrume Example */ = {
isa = PBXGroup;
children = (
F2D7BA2120A4812C00D5EE66 /* animated.gif */,
F2D7BA1E20A47FB500D5EE66 /* AnimatedGifViewController.swift */,
F2A5201A1B130C7E00924912 /* AppDelegate.swift */,
F2D959941B1A15ED00073772 /* DemoCell.swift */,
F2A520211B130C7E00924912 /* Images.xcassets */,
Expand Down Expand Up @@ -276,6 +282,7 @@
files = (
F2A520201B130C7E00924912 /* Main.storyboard in Resources */,
F2A520251B130C7E00924912 /* LaunchScreen.xib in Resources */,
F2D7BA2220A4812C00D5EE66 /* animated.gif in Resources */,
F2A520221B130C7E00924912 /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -296,6 +303,7 @@
files = (
E77809E31D17821400CC60F1 /* SingleImageModalViewController.swift in Sources */,
F2D959911B1A140200073772 /* SingleURLViewController.swift in Sources */,
F2D7BA1F20A47FB500D5EE66 /* AnimatedGifViewController.swift in Sources */,
94D6B2121E1411B100927735 /* SingeImageBackgroundColorViewController.swift in Sources */,
F2A5201D1B130C7E00924912 /* ViewController.swift in Sources */,
F2D959951B1A15ED00073772 /* DemoCell.swift in Sources */,
Expand Down
17 changes: 17 additions & 0 deletions Example/Agrume Example/AnimatedGifViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Copyright © 2018 Schnaub. All rights reserved.
//

import UIKit
import Agrume
import SwiftyGif

final class AnimatedGifViewController: UIViewController {

@IBAction func openImage(_ sender: Any?) {
let image = UIImage(gifName: "animated.gif")
let agrume = Agrume(image: image, background: .blurred(.regular))
agrume.show(from: self)
}

}
Loading

0 comments on commit 0191791

Please sign in to comment.