你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> Swift3.0學習理論

Swift3.0學習理論

編輯:IOS開發綜合

代碼+知識點總結

fileprivate struct DataInMemory{
    var dataKey:String//數據對應的key
    var data:Data//數據
    var timeStamp:Date//上次訪問數據(存、取、改)的時間
    
    init(dataKey:String,data:Data,timeStamp:Date){//初始化辦法
        self.dataKey = dataKey
        self.data = data
        self.timeStamp = timeStamp
    }
}
1.訪問修飾符:

private:修飾的屬性和辦法只能被本類(構造體)訪問。修飾類(構造體)自身時,經過實驗,效果和fileprivate相反,文件外部可見。

fileprivate:文件外部可見

internal:整個框架、模塊內可見

public:地下,但其它框架、模塊中不可被重寫或承繼

open:地下,且有限制

2.構造體與類相關知識點:

(1)構造體是值類型,類是援用類型

(2)當類是let時,可修正其屬性,但構造體是let時,其屬性也不可被修正(構造體是值類型,修正其屬性,會招致新正本的發生,與let相悖)

(3)構造體中的辦法要修正本身屬性時,要加mutating關鍵字修飾(構造體是值類型,修正其屬性,會招致新正本的發生,所以要加mutating告知編譯器處置)

(4)Array Dict Set Int Float Bool String Double等都是構造體

(5)構造體不具有承繼特性


open class ZDataCache
    //單例對象,靜態對象+公有初始化辦法
    public static let shareCache = ZDataCache()
    
    private var _maxDataInMemory:Int//隊列最大長度
    //借助計算屬性,完成_maxDataInMemory的存取控制
    public var maxDataInMemory:Int{//隊列最大長度
        get{
            return _maxDataInMemory
        }
        set{
            if (newValue > 30){
                _maxDataInMemory = 30
            }
            else if(newValue <= 0){
                _maxDataInMemory = 15
            }
            else{
                _maxDataInMemory = newValue
            }
        }
    }
    
    private let ioQueue:DispatchQueue //操作隊列
    private var memoryCache:[DataInMemory] //內存緩存隊列
    private var cleanMemoryTimer:Timer!//緩存自動清算定時器
    //本地緩存根目錄地址
    private let dataCachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.libraryDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0].appending("/DataCache/")
    
    private init(){
        ioQueue = DispatchQueue(label: "zdc.io.queue")//串行隊列,避免多線程競爭
        memoryCache = []
        _maxDataInMemory = 15
    
        //創立緩存目錄
        let fileManager = FileManager.default
        if !fileManager.fileExists(atPath: dataCachePath) {
            do{
                try fileManager.createDirectory(at: URL(fileURLWithPath: dataCachePath), withIntermediateDirectories: true, attributes: nil)
            }catch{
                NSLog("create cache dir error")
            }
        }
        //活期肅清緩存計時器
        //當用weak修飾一個變量時,這個變量自動被零碎聲明為可選型變量
        weak var wSelf = self
        cleanMemoryTimer = Timer(timeInterval: 180, repeats: true, block: { (timer:Timer) in
            //清算緩存
            wSelf!.cleanDataInMemory()
        })
        //不要求計時特別精准,僅在defaultRunLoopMode下任務即可
        RunLoop.main.add(cleanMemoryTimer, forMode:RunLoopMode.defaultRunLoopMode)
    }
3.單例的完成:

在swift中完成單例形式非常復雜,只需靜態變量+公有初始化辦法即可。swift在執行時靜態變量初始化時,會自動參加dispatch_once機制保證多線程訪問狀況下的平安

Swift3.0學習實踐

timer在停止初始化的進程中需求完成回調閉包或許指定target及selector,這樣就會不可防止的會訪問到self,但此時編譯器便會報錯,我們在一切成員變量尚未初始化(timer正在初始化中)便訪問了self。

處理的方式是private var cleanMemoryTimer:Timer!

告知編譯器,承諾cleanMemoryTimer在運用時一定是存在初始值的,這樣編譯器就不會再對cleanMemoryTimer的初始化狀況停止反省,其它變量完成初始化後,對象(self)就可以運用了

或許private var cleanMemoryTimer:Timer?

將cleanMemoryTimer聲明為可選型,默許會賦初值nil(不建議運用這種方式)

6.weak與unowned

swift與oc一樣,采用基於援用計數的內存管理機制,異樣也存在強弱援用的概念,在oc中我們經過weak描繪一個弱援用關系,在swift中異樣也有weak,它們的作用也完全分歧,weak修飾的指針指向的對象被銷毀後,該指針會被置為nil.但是,swift中引入了可選型的概念,同時還存在var與let的區別。假如一個對象要被賦值為nil,則必需為可選型,同時從指向一個對象到被置為nil,有一個變化進程,所以又必需是一個var,於是就要求weak修飾的是必需是一個可選型var(當用weak修飾一個變量時,這個變量自動就會被聲明為可選型)。但有些狀況下,我們想修飾一個弱援用關系,但是設計上被修飾的指針不是一個可選型或許不是一個var(變量),這個時分就可以用unowned對其停止描繪,unowned異樣描繪一個弱援用關系,但不具有自動置空(nil)的才能,於是也就沒有了可選型及var的要求。不過在運用unowned時要格外小心,防止呈現野指針問題。


     /*數據的存儲或更新
     在內存緩存中找能否存在key相反的舊數據
     存在:更新緩存中對應的數據內容及訪問時間,將對應緩存數據挪到隊尾,將新數據寫到磁盤
     不存在:將數據拔出內存緩存隊尾,將數據寫到磁盤
     */
    public func addDataToCache(key:String,data:Data)->Void{
        //guard的運用
        guard !key.isEmpty else{
            return
        }
        guard !data.isEmpty else{
            return
        }
        let md5Key = md5(str: key)
        let dataPath = dataCachePath.appending(md5Key)
        ioQueue.async {
            //可選型
            var dataFindInMemory:DataInMemory? = nil
            let dataCountInMemory = self.memoryCache.count
            for i in 0..<dataCountInMemory{
                var dataInMemory = self.memoryCache[i]
                if(dataInMemory.dataKey == md5Key){
                    //更新數據,數據有能夠發生變化
                    dataInMemory.data = data
                    //更新訪問時間
                    dataInMemory.timeStamp = Date()
                    dataFindInMemory = dataInMemory
                    self.memoryCache.remove(at: i)
                    break
                }
            }
            //if的可選型解包
            if let dataFindInMemory = dataFindInMemory{
                self.memoryCache.append(dataFindInMemory)
            }
            else{
                self.insertDataToMemory(data: data, key: md5Key)
            }
        
            do{
                try data.write(to: URL(fileURLWithPath: dataPath), options: Data.WritingOptions.atomicWrite)
            }catch{
                NSLog("write error")
            }
        }
    }
7.閉包中為什麼要加self.

在同一個類外部,當我們想要訪問類的其它成員變量或辦法時只需直接調用即可,如

let md5Key = md5(str: key)//調用md5加密辦法
let dataPath = dataCachePath.appending(md5Key)//運用dataCachePath屬性
但是,即使是在類外部,假如我們在一個閉包中去直接訪問成員變量或辦法,編譯器是會報錯的,如

Swift3.0學習實踐 /*數據讀取 在內存緩存中找能否存在key相反的數據 存在:更新緩存中對應的數據的訪問時間,將對應緩存數據挪到隊尾,前往內存緩存中數據 不存在:從磁盤讀取數據,將數據拔出內存緩存隊尾 */ public func readDataFromCache(key:String)->Data?{ guard !key.isEmpty else{ return nil } let md5Key = md5(str: key) let dataPath = dataCachePath.appending(md5Key) var data:Data? = nil let group = DispatchGroup() var tempDataInMemory:DataInMemory? = nil ioQueue.async(group: group){ group.enter() let dataCountInMemory = self.memoryCache.count for i in 0..<dataCountInMemory{ var dataInMemory = self.memoryCache[i] if(dataInMemory.dataKey == md5Key){ tempDataInMemory = dataInMemory data = dataInMemory.data dataInMemory.timeStamp = Date() self.memoryCache.remove(at: i) break } } if let tempDataInMemory = tempDataInMemory{ self.memoryCache.append(tempDataInMemory) } else { do{ try data = Data(contentsOf: URL(fileURLWithPath: dataPath)) self.insertDataToMemory(data: data!, key: md5Key) }catch{ NSLog("read error") } } group.leave() } group.wait() return data }
     /*數據刪除
     在內存緩存中找能否存在key相反的數據
     存在:刪除內存緩存中對應數據,刪除磁盤數據
     不存在:刪除磁盤數據
     */
    public func removeDataFromCache(key:String)->Void{
        guard !key.isEmpty else{
            return
        }
        let md5Key = md5(str: key)
        let dataPath = dataCachePath.appending(md5Key)
        ioQueue.async {
            let dataCountInMemory = self.memoryCache.count
            for i in 0..<dataCountInMemory{
                let dataInMemory = self.memoryCache[i]
                if (dataInMemory.dataKey == md5Key){
                    self.memoryCache.remove(at: i)
                    break
                }
            }
            do{
                try FileManager.default.removeItem(at: URL(fileURLWithPath: dataPath))
            }catch{
                NSLog("remove error")
            }
        }
    }
    /*在內存緩存中參加一條新數據
    緩存隊列能否已滿?
    是:移除隊頭最老數據,在隊尾參加一條新數據
    否:在隊尾參加一條新數據
    */
    private func insertDataToMemory(data:Data,key:String)->Void{
        let dataInMemory = DataInMemory(dataKey: key, data: data, timeStamp: Date())
        let dataCountInMemory = memoryCache.count
        if(dataCountInMemory < maxDataInMemory){
            memoryCache.append(dataInMemory)
        }
        else{
            memoryCache.remove(at: 0)
            memoryCache.append(dataInMemory)
        }
    }
    /*緩存清算
    從隊尾開端遍歷,直到找到一條上次訪問的時間超越180秒的數據
    從緩存隊列中刪除這條及這條之前的一切數據(隊列中數據都是依照訪問時間,從遠到近陳列好的)
    */
    private func cleanDataInMemory()->Void{
        let dataCountInMemory = memoryCache.count
        var dirtyDataIndex:Int? = nil
        let currentDate = Date()
        for i in (0..<dataCountInMemory).reversed(){
            let dataInMemory = memoryCache[i]
            if(currentDate.timeIntervalSince(dataInMemory.timeStamp) >= 180){
                dirtyDataIndex = i
            }
        }
        if let dirtyDataIndex = dirtyDataIndex{
            memoryCache.removeSubrange(0...dirtyDataIndex)
        }
    }
    //md5加密
    private func md5(str:String)->String{
        let cStr = str.cString(using: String.Encoding.utf8)
        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 16)
        CC_MD5(cStr!,(CC_LONG)(strlen(cStr!)), buffer)
        let md5String = NSMutableString()
        for i in 0 ..< 16{
            md5String.appendFormat("%02x", buffer[i])
        }
        free(buffer)
        return md5String as String
    }

都是練習代碼,很多中央不是很嚴謹,同時也是第一個swift理論,如有了解或完成不對的中央,歡送指正

【Swift3.0學習理論】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved