[Swift 3.0] One function to implementation auto scroll ad. view

Abstract

How to automatic scroll
New features in Swift 3.0
How to Async load image with memery and disk cache policy like SDWebImage.

Introduction

....................................................................................................
A class with ad. pics auotmatic scrolling build in swift with image cache policy used.


Installtion

Manual:

Download This Project and drag the FGSwiftAutoScrollView folder into your peroject, do not forget to ensure "copy item if need" being selected.

Usage

  • Load Web Images:
    //MARK:-
    //MARK:automatic scrollView with web images
    convenience init(frame:CGRect, placeHolder placeHolderImage:UIImage?,remoteImageUrls imgs:Array?, selectImageAction imageDidSelectedAction:@escaping FGImageClickBlock){
        
        self.init(frame: frame)
        self.createLoacalCacheFolder()
        self.placeHolderImage=placeHolderImage
        self.didSelectedImageAction=imageDidSelectedAction
        self.imageUrlArray=imgs
        DispatchQueue.main.async {
            self.createScrollView()
        }
    }
  • Load Local Images:
    //MARK:automatic scrollView with local images
    convenience init(frame:CGRect,placeHolder placeHolderImage:UIImage?,localImageNames imgs:Array?, selectImageAction imageDidSelectedAction:@escaping FGImageClickBlock){
        
        self.init(frame: frame)
        self.placeHolderImage=placeHolderImage
        var fileUrlsArray:Array=[]
        for name in imgs!{
            
            var path:String?
            if name.hasSuffix("jpg")||name.hasSuffix("png"){
                path=Bundle.main.path(forResource: name, ofType: nil)
            }
            else{
                path=Bundle.main.path(forResource: name, ofType: "png")
            }
            if path==nil{
                path=""
            }
            path=path?.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
            let fullPath=String.init(format: "file://%@", path!)
            fileUrlsArray.append(fullPath)
        }
        self.didSelectedImageAction=imageDidSelectedAction
        self.imageUrlArray=fileUrlsArray
        self.createScrollView()
    }
  • you can simply use the srcoll call back block if need (not necessary)
self.banner?.imageDidScrolledBlock={ (currentIndex) in

    print("滚到到了第"+String(currentIndex)+"页了")
}

Explain:

If you don't need add image tap action, property didSelectedImageAction block can be nil.

How to implementation

Create a class:FGSwiftAutoScrollView.swift and confirm to the UIScrollViewDelegate

class FGSwiftAutoScrollView: UIView,UIScrollViewDelegate{

}

Add some properties

    //auto scroll interval
    let fg_scrollInterval=3.0
    //disk cache path
    let fg_cachePath=NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).last!+"/FGGAutomaticScrollViewCache"
    //memery cache
    let fg_imageCache=NSCache()
    //maximun disk chache cycle
    let fg_maxCacheCycle=TimeInterval(7*24*3600)
    // tap image call action call back
    private var didSelectedImageAction:FGImageClickBlock?
    //image did scrolled call back
    public var  imageDidScrolledBlock:FGImageScrolledBlock?
    //data source
    public var  imageUrlArray:Array?{
        //redifine setter
        didSet{
            //refresh UI on main queue
            DispatchQueue.main.async {
                
                self.createScrollView()
            }
        }
    }
    //main scrollView
    private var scroll:UIScrollView?
    //to ensure automatic scroll
    private var timer:Timer!
    //page control to show current page index
    private var pageControl:UIPageControl!
    //placeHolder image
    var placeHolderImage:UIImage?

Override initWithFrame:

override init(frame:CGRect){
        super.init(frame:frame)
        self.createLoacalCacheFolder()
    }

Create an area for disk image cache

    //MARK:- create cache area
    //MARK:create a cache area to cache web images
    private func createLoacalCacheFolder(){
        
        if !FileManager.default.fileExists(atPath: fg_cachePath){
            do{
                try FileManager.default.createDirectory(atPath: fg_cachePath, withIntermediateDirectories: true, attributes: nil)
                
            }catch{
                
            }
        }
    }

Give two convenience functions

    //MARK:-Load Web Image
    //MARK:automatic scrollView with web images
    convenience init(frame:CGRect, placeHolder placeHolderImage:UIImage?,remoteImageUrls imgs:Array?, selectImageAction imageDidSelectedAction:@escaping FGImageClickBlock){
        
        self.init(frame: frame)
        self.placeHolderImage=placeHolderImage
        self.didSelectedImageAction=imageDidSelectedAction
        self.imageUrlArray=imgs
        DispatchQueue.main.async {
            self.createScrollView()
        }
    }
    //MARK:Load Local Image
    //MARK:automatic scrollView with local images
    convenience init(frame:CGRect,placeHolder placeHolderImage:UIImage?,localImageNames imgs:Array?, selectImageAction imageDidSelectedAction:@escaping FGImageClickBlock){
        
        self.init(frame: frame)
        self.placeHolderImage=placeHolderImage
        var fileUrlsArray:Array=[]
        for name in imgs!{
            
            var path:String?
            if name.hasSuffix("jpg")||name.hasSuffix("png"){
                path=Bundle.main.path(forResource: name, ofType: nil)
            }
            else{
                path=Bundle.main.path(forResource: name, ofType: "png")
            }
            if path==nil{
                path=""
            }
            path=path?.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)
            let fullPath=String.init(format: "file://%@", path!)
            fileUrlsArray.append(fullPath)
        }
        self.didSelectedImageAction=imageDidSelectedAction
        self.imageUrlArray=fileUrlsArray
        self.createScrollView()
    }

Create main scroll view

    //MARK:-
    //MARK:create scroll view
    private func createScrollView(){
        
        if self.scroll != nil{
            
            for sub in self.subviews {
                
                sub.removeFromSuperview()
            }
            self.scroll?.removeFromSuperview()
            self.scroll=nil
        }
        self.scroll=UIScrollView.init(frame: self.bounds)
        self.addSubview(self.scroll!)
        self.scroll?.delegate=self
        var count:Int?;
        if self.imageUrlArray==nil{
            count=0
        }else{
            count=self.imageUrlArray?.count
        }
        let width:CGFloat=CGFloat((count!+1))*self.bounds.size.width;
        let height:CGFloat=self.bounds.size.height;
        self.scroll?.contentSize=CGSize.init(width: width, height: height)
        
        self.scroll?.isPagingEnabled=true
        self.scroll?.showsHorizontalScrollIndicator=false
        
        if self.timer != nil{
            
            self.timer.invalidate()
            self.timer=nil
        }
        //detach the timer
        self.timer=Timer.scheduledTimer(withTimeInterval: fg_scrollInterval, repeats: true, block: { (t) in
            
            if self.imageUrlArray?.count==0{
                return
            }
            var index=Int((self.scroll?.contentOffset.x)!/self.bounds.size.width);
            index+=1
            if index==self.imageUrlArray?.count{
                index=0
            }
            if self.imageDidScrolledBlock != nil{
                
                self.imageDidScrolledBlock?(UInt(index))
            }
            self.pageControl.currentPage=index
            UIView.animate(withDuration: 0.2, animations: {
                self.scroll?.contentOffset=CGPoint.init(x: self.bounds.size.width*CGFloat(index), y: 0)
            })
        })
        if count!>0{
            for i in 0...count!{
                
                let xpos=CGFloat(i)*self.bounds.size.width
                let frm=CGRect.init(x: xpos, y: 0, width: self.bounds.size.width, height: self.bounds.size.height)
                let imv=UIImageView.init(frame: frm)
                imv.image=self.placeHolderImage
                imv.isUserInteractionEnabled=true
                let tap:UITapGestureRecognizer=UITapGestureRecognizer.init(target: self, action:#selector(FGSwiftAutoScrollView.tapImage))
                imv.addGestureRecognizer(tap)
                self.scroll?.addSubview(imv)
                var urlString:String?
                if i

Impletatin of sroll view delegate

    //MARK:-
    //MARK:UIScrollView Delegate
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        
        var index=Int((self.scroll?.contentOffset.x)!/self.bounds.size.width);
        if index==self.imageUrlArray?.count{
            index=0;
        }
        if self.imageDidScrolledBlock != nil{
            
            self.imageDidScrolledBlock?(UInt(index))
        }
        self.pageControl.currentPage=index
        self.scroll?.contentOffset=CGPoint.init(x: self.bounds.size.width*CGFloat(index), y: 0)
    }

Implementation of tap image action

  //MARK:-
    //MARK: Tag Image Action
    func tapImage(){
        
        if self.didSelectedImageAction != nil{
            
            self.didSelectedImageAction?(UInt(self.pageControl.currentPage));
        }
    }

Destroy the timer in deinit

deinit{
        if self.timer != nil{
            self.timer .invalidate()
            self.timer=nil
        }
    }

Write an extension to async download image like SDWebImage

extension FGSwiftAutoScrollView{

}

Async image loading like SDWebImage with cache in memery an disk

    func fg_setImageWithUrlString(imageView:UIImageView?,urlString:String?,placeHolder:UIImage?){
        
        if imageView==nil{
            return
        }
        imageView?.image=placeHolder
        if urlString==nil{
            return
        }
        var cachePath=fg_cachePath+"/"+String(describing: urlString?.hash)
        if (urlString?.hasPrefix("file://"))!{//local path
            cachePath=urlString!
        }
        //check the memery chache exist or not(both local and web images)
        var data=fg_imageCache.object(forKey: cachePath as AnyObject)
        if (data != nil) {//exist in memery cache
            
            DispatchQueue.main.async{
                imageView?.image=UIImage(data: data as! Data)
            }
        }else{//not in memery cache,check if exist in disk or not
            //local images
            if (urlString?.hasPrefix("file://"))!{
                
                let url:NSURL=NSURL.init(string: urlString!)!
                do{
                    try data=Data.init(contentsOf: url as URL) as AnyObject?
                }catch{
                    
                }
                //if local image exist
                if data != nil{
                    
                    fg_imageCache.setObject(data as AnyObject, forKey: cachePath as AnyObject)
                    DispatchQueue.main.async{
                        imageView?.image=UIImage(data: data as! Data)
                    }
                }
                else{//local image is not exist,just ingnore
                    //ingnore
                }
            }
                //web images
            else{
                //check if exist in disk
                let exist=FileManager.default.fileExists(atPath: cachePath)
                if exist {//exist in disk
                    //check if expired
                    var attributes:Dictionary?
                    do{
                        try attributes=FileManager.default.attributesOfItem(atPath: cachePath)
                    }catch{
                        
                    }
                    let createDate:Date?=attributes?[FileAttributeKey.creationDate] as! Date?
                    let interval:TimeInterval?=Date.init().timeIntervalSince(createDate!)
                    let expired=(interval! > fg_maxCacheCycle)
                    if expired{//expired
                        //download image
                        self.donwloadDataAndRefreshImageView(imageView: imageView, urlString: urlString, cachePath: cachePath)
                    }
                    else{//not expired
                        //load from disk
                        let url:NSURL=NSURL.init(string: urlString!)!
                        do{
                            try data=Data.init(contentsOf: url as URL) as AnyObject?
                        }catch{
                            
                        }
                        if data != nil{//if has data
                            //cached in memery
                            fg_imageCache.setObject(data as AnyObject, forKey: cachePath as AnyObject)
                            DispatchQueue.main.async{
                                imageView?.image=UIImage(data: data as! Data)
                            }
                        }
                        else{//has not data
                            //remove item from disk
                            let url:NSURL=NSURL.init(string: urlString!)!
                            do{
                                try data=Data.init(contentsOf: url as URL) as AnyObject?
                            }catch{
                                
                            }
                            //donwload agin
                            self.donwloadDataAndRefreshImageView(imageView: imageView, urlString: urlString, cachePath: cachePath)
                        }
                    }
                }
                    //not exist in disk
                else{
                    //download image
                    self.donwloadDataAndRefreshImageView(imageView: imageView, urlString: urlString, cachePath: cachePath)
                }
            }
        }
    }

Donwload Image Task

    //async download image
    private func donwloadDataAndRefreshImageView(imageView:UIImageView?,urlString:String?,cachePath:String!){
        
        do{
            try FileManager.default.removeItem(atPath: cachePath)
        }catch{
            
        }
        //download data
        let url=URL.init(string: urlString!)
        let session=URLSession.shared.dataTask(with: url!, completionHandler: { (resultData, res, err) in
            let fileUrl=URL.init(fileURLWithPath: cachePath)
            do{
                try resultData?.write(to: fileUrl, options:.atomic)
            }catch{
                
            }
            self.fg_imageCache.setObject(resultData as AnyObject, forKey: cachePath as AnyObject)
            if resultData != nil{
                DispatchQueue.main.async{
                    imageView?.image=UIImage(data: resultData!)
                }
            }
            else{
                //ingnore
            }
        })
        session.resume()
    }

End. Attached the address of my source code on GitHub

FGSwiftAutoScrollView Hope your star, fork or pull request.

Support Me

  • Blog: CGPointZeero
  • GitHub: Insfgg99x
  • Mooc: CGPointZero
  • Jianshu: CGPointZero
  • Email: [email protected]

................................................................................................

Copyright (c) 2016 CGPointZero. All rights reserved.

[Swift 3.0] One function to implementation auto scroll ad. view_第1张图片

你可能感兴趣的:([Swift 3.0] One function to implementation auto scroll ad. view)