Swift 開屏廣告的實現 (支援本地與網路的圖片,動態圖,視訊)

z小志發表於2018-01-22

###原理 使用者在使用app的時候,使用者肯定會多次開啟app的,但是如果網速慢圖片大,總不能讓使用者看3秒預設啟動圖吧?那樣體驗太不好了,因此還是加入快取機制比較好。我的實現思路是,第一次不讓使用者去看這個3秒廣告了,直接略過,開一個執行緒去快取這張圖片。第二次使用者再啟動app的時候,判斷廣告有效時間顯示圖片 ,gif、視訊同理。

效果圖

Example.gif
![
gif.gif
]
vidio.gif

####部分程式碼

AppDelegate  需要顯示廣告圖的時候新增以下程式碼

import MDSplashScreen

    if type == .localImage{
        let adView = MDSplashScreenView.init(type: .localImage)
        adView.img = "localImage.JPG"
        adView.linkUrl = "https://www.baidu.com/"
        adView.imageValidTime = "03/02/2018 14:25"
        adView.showSplashScreenWithTime(showTime: 3)
    }else if type == .localGif{
        let adView = MDSplashScreenView.init(type: .localGif)
        adView.img = "localGIf"
        adView.linkUrl = "https://www.baidu.com/"
        adView.imageValidTime = "03/02/2018 14:25"
        adView.showSplashScreenWithTime(showTime: 3)
    }else if type == .localVidio{
        let adView = MDSplashScreenView.init(type: .localVidio)
        adView.img = "localVidio"
        adView.linkUrl = ""
        adView.imageValidTime = "03/02/2018 14:25"
        adView.videoCycleOnce = false //是否迴圈
        adView.showSplashScreenWithTime(showTime: 0)
    }else if type == .netImage{
        let splashScreenManager = MDSplashScreenManager.sharedManager
        if UserDefaults.standard.object(forKey: AdImageName) != nil{
            let imageName = UserDefaults.standard.object(forKey: AdImageName) as! String
            let filepath = splashScreenManager.getFilePathWithName(name: imageName)
            let isExist = splashScreenManager.isFileExistWithFilePath(filePath: filepath)
            if isExist{
                let adView = MDSplashScreenView.init(type: .netImage)
                adView.img = filepath
                adView.linkUrl = UserDefaults.standard.object(forKey: AdLinkUrl) as? String
                adView.imageValidTime = UserDefaults.standard.object(forKey: AdValidTime) as? String
                adView.showSplashScreenWithTime(showTime: 3)
            }
        }

        splashScreenManager.getAdvertisingData(url: "http://img1.126.net/channel6/2016/022471/0805/2.jpg?dpi=6401136", validTime: "03/02/2018 14:25", linkUrl: "https://www.jianshu.com/u/90028000c41d", type: .netImage)
    }else if type == .netGif{
        let splashScreenManager = MDSplashScreenManager.sharedManager
        if UserDefaults.standard.object(forKey: AdGifName) != nil{
            let gifName = UserDefaults.standard.object(forKey: AdGifName) as! String
            let filepath = splashScreenManager.getFilePathWithName(name: gifName)
            let isExist = splashScreenManager.isFileExistWithFilePath(filePath: filepath)
            if isExist{
                let adView = MDSplashScreenView.init(type: .netGif)
                adView.img = filepath
                adView.linkUrl = UserDefaults.standard.object(forKey: AdLinkUrl) as? String
                adView.imageValidTime = UserDefaults.standard.object(forKey: AdValidTime) as? String
                adView.showSplashScreenWithTime(showTime: 3)
            }
        }
        
        splashScreenManager.getAdvertisingData(url: "http://yun.it7090.com/image/XHLaunchAd/pic05.gif", validTime: "03/02/2018 14:25", linkUrl: "https://www.jianshu.com/u/90028000c41d", type: .netGif)
    }else if type == .netVidio{
        let splashScreenManager = MDSplashScreenManager.sharedManager
        if UserDefaults.standard.object(forKey: AdViedioName) != nil{
            let vidioName = UserDefaults.standard.object(forKey: AdViedioName) as! String
            let filepath = splashScreenManager.getFilePathWithName(name:vidioName)
            let isExist = splashScreenManager.isFileExistWithFilePath(filePath: filepath)
            if isExist{
                let adView = MDSplashScreenView.init(type: .netVidio)
                adView.img = filepath
                adView.linkUrl = UserDefaults.standard.object(forKey: AdLinkUrl) as? String
                adView.imageValidTime = UserDefaults.standard.object(forKey: AdValidTime) as? String
                adView.showSplashScreenWithTime(showTime: 0)
            }
        }
        
        splashScreenManager.getAdvertisingData(url: "http://yun.it7090.com/video/XHLaunchAd/video03.mp4", validTime: "03/02/2018 14:25", linkUrl: "https://www.jianshu.com/u/90028000c41d", type: .netVidio)
    }


MDSplashScreenView

顯示廣告圖
    open func showSplashScreenWithTime(showTime:Int){
        if type == .localImage{
            self.adImageView.image = UIImage.init(named: img!)
        }else if type == .localGif{
            self.adImageView.loadGif(name: img!)
        }else if type == .netImage{
            self.adImageView.image = UIImage.init(contentsOfFile: self.img!)
        }else if type == .netGif{
            let data = try? Data.init(contentsOf: URL.init(fileURLWithPath: self.img!))
            if data == nil{
                self.dismiss()
            }else{
                self.adImageView.image = UIImage.gif(data: data!)
            }
        }else if type == .localVidio{
            let filePath = Bundle.main.path(forResource: img!, ofType: "mp4")
            let videoURL = URL(fileURLWithPath: filePath!)
            let playerItem = AVPlayerItem.init(url: videoURL)
            self.videoPlayer?.player = AVPlayer.init(playerItem: playerItem)
            self.videoPlayer?.player?.play()
        }else if type == .netVidio{
            let videoURL = URL(fileURLWithPath:  img!)
            let playerItem = AVPlayerItem.init(url: videoURL)
            self.videoPlayer?.player = AVPlayer.init(playerItem: playerItem)
            self.videoPlayer?.player?.play()
        }
    
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MM/dd/yyyy HH:mm"
        dateFormatter.string(from: Date())

        let  timeStampString = self.imageValidTime
        if timeStampString == nil{
            print("結束時間儲存失敗")
            self.dismiss()
        }
        let validTimeDate = dateFormatter.date(from: timeStampString!)

        var result:ComparisonResult?
        result = validTimeDate?.compare(Date())
        //將存下來的日期和當前日期相比,如果當前日期小於存下來的時間,則可以顯示廣告頁,反之則不顯示
        if result == .orderedAscending{
            dismiss()
        }else{
            if showTime != 0{
                self.showTime = showTime
                countButton.setTitle("跳過\(showTime)", for: .normal)
                startTimer()
            }else{
                countButton.setTitle("跳過", for: .normal)
            }
            let window = UIApplication.shared.delegate?.window
            window??.isHidden = false
            window??.addSubview(self)
        }
        
    }

獲取圖片
open func getAdvertisingData(url:String,validTime:String,linkUrl:String,type:MDSplashScreenType){
        // 獲取名稱
        let stringArr = url.components(separatedBy: "/")
        let name: String? = stringArr.last
        // 拼接沙盒路徑
        let filePath: String = getFilePathWithName(name: name!)
        let isExist: Bool = isFileExistWithFilePath(filePath: filePath)
        if !isExist {
            // 如果該資源不存在,則刪除老的,下載新的
            if type == .netImage{
                downloadAdDataWithUrl(url: url, name: name!, linkUrl: linkUrl, validTime: validTime,key: AdImageName)
            }else if type == .netGif{
                downloadAdDataWithUrl(url: url, name: name!, linkUrl: linkUrl, validTime: validTime,key: AdGifName)
            }else if type == .netVidio{
                downloadAdDataWithUrl(url: url, name: name!, linkUrl: linkUrl, validTime: validTime,key: AdViedioName)
            }
        }
    }
非同步下載圖片
    //下載資源到本地
    fileprivate func downloadAdDataWithUrl(url:String,name:String,linkUrl:String,validTime:String,key:String){
        DispatchQueue.global().async {
            let data = try? Data.init(contentsOf: URL(string: url)!)
            if data != nil{
                let filePath  = self.getFilePathWithName(name: name)
                let gifData = NSData.init(data: data!)
                let isWrite = gifData.write(toFile: filePath, atomically: true)
                print(filePath)
                if isWrite{
                    let adImageName:String? = UserDefaults.standard.object(forKey: key) as? String
                    if name == adImageName{
                        self.deleteOldCache()
                    }
                    UserDefaults.standard.setValue(name, forKey: key)
                    UserDefaults.standard.setValue(linkUrl, forKey: AdLinkUrl)
                    UserDefaults.standard.setValue(validTime, forKey: AdValidTime)
                    UserDefaults.standard.synchronize()
                }else{
                    print("儲存失敗")
                }
            }else{
                print("Data為空,請檢查您的網路或連結")
            }
        }
    }
    

//點選事件
@objc func toAdVC(){
        //點選廣告圖時,廣告圖消失,同時像首頁傳送通知,並把廣告頁對應的地址傳給首頁
        self.dismiss()
        NotificationCenter.default.post(name: NSNotification.Name.init(ToAdVC), object: linkUrl, userInfo: nil)
    }

複製程式碼

支援 pod

pod 'MDSplashScreen'
複製程式碼

附Demo地址

有什麼問題歡迎提出。

相關文章