GIF広告への対応

UIImageViewはアニメーションGIFを再生できないため、GIF広告を表示したい利用者にGIFデータを再生する方法を紹介します。

  • 下記の方法と他に、SwiftGifのようなライブラリを利用することも可能です。

GIF広告の判別

カスタムインフィード広告パラメータにあるプロパティ imageURL による画像データをロードする際に、レスポンスの mimeTypeimage/gifによって画像データがGIFかどうかを判別することができます。

        URLSession.shared.dataTask(with: URLRequest(url: instreamInfoModel.imageURL!)) { (data, response, error) in
            guard let data = data, let response = response as? HTTPURLResponse, error == nil else {
                return
            }
            DispatchQueue.main.async(execute: {
                if (response.mimeType == "image/gif") {
                    //GIFと判別
                } else {
                }
            })
            }.resume()

GIF広告の表示

Image I/0を利用してデータからイメージソース抽出してanimationImages で再生することが可能です。 広告の実装例を挙げます。

    //imageViewをsubViewとして追加し、imageViewのstartAnimating()をコールしてください
    guard let imageView = self.createGifImageFromData(data: data as NSData, bounds: yourView.containerView.bounds) else {return}
    yourView.containerView.addSubview(imageView)
    imageView.startAnimating()

    func createGifImageFromData (data : NSData, bounds : CGRect) -> UIImageView?  {
        guard let gifImagesSource = CGImageSourceCreateWithData(data as CFData, nil) else {return nil}
        //GIF画像の枚数
        let gifImagesCount = CGImageSourceGetCount(gifImagesSource)
        var gifImagesArray = [UIImage]()
        var totalDuration : TimeInterval = 0
        let imageView = UIImageView(frame: bounds)

        for i in 0 ..< gifImagesCount {
            guard let cgImage = CGImageSourceCreateImageAtIndex(gifImagesSource, i, nil) else { continue }
            let image = UIImage(cgImage: cgImage)
            if i == 0 {
                imageView.image = image
            }
            gifImagesArray.append(image)

            // Durationのデフォルト値
            var frameDuration : Float = 0.1;
            guard let properties = CGImageSourceCopyPropertiesAtIndex(gifImagesSource, i, nil) else {
                totalDuration += frameDuration
                continue }
            guard let gifDict = (properties as NSDictionary)[kCGImagePropertyGIFDictionary] as? NSDictionary else {
                totalDuration += frameDuration
                continue }
            if let delayTimeUnclampedProp = gifDict[kCGImagePropertyGIFUnclampedDelayTime as String] as? NSNumber {
                frameDuration = delayTimeUnclampedProp.floatValue
            } else {
                if let delayTimeProp = gifDict[kCGImagePropertyGIFDelayTime as String] as? NSNumber {
                    frameDuration = delayTimeProp.floatValue
                }
            }
            // 小さすぎないように
            if frameDuration < 0.01 {
                frameDuration = 0.1;
            }
            totalDuration += frameDuration
        }
        imageView.animationImages = gifImagesArray
        // 画像ごとの表示時間が同じ
        imageView.animationDuration = TimeInterval(totalDuration)
        // GIFのループを無限とする
        imageView.animationRepeatCount = 0
        imageView.contentMode = .scaleAspectFit
        imageView.image = UIImage(data: data as Data)
        return imageView
    }
}