從0開始學Swift筆記整理(五)

這是跟在上一篇博文後續內容:程序員

——Core Foundation框架

Core Foundation框架是蘋果公司提供一套概念來源於Foundation框架,編程接口面向C語言風格的API。雖然在Swift中調用這種C語言風格的API比較麻煩,可是在OS X和iOS開發過程當中,有時候使用Core Foundation框架的API是很是方便的,例如在與C語言混合編碼的時候。
Core Foundation框架與Foundation框架緊密相關,他們具備與相同的接口,可是不一樣。Core Foundation框架是基於C語言風格的,而Foundation框架是基於Objective-C語言風格的。在OS X和iOS程序代碼中常常會有多種語言風格的代碼混合在一塊兒的狀況,這使得咱們開發變得更加麻煩。
數據類型映射
Core Foundation框架提供了一些不透明的數據類型,這些數據類型封裝了一些數據和操做,他們也能夠稱爲「類」,他們都繼承於CFType類,CFType是所用Core Foundation框架類型的根類。這些數據類型在Foundation框架中都有相應的數據類型與之對應,這些數據類型也有一些與Swift原生數據類型有對應關係。
編程

看看Swift原生類型與Core Foundation類型之間的轉換示例:設計模式

importCoreFoundationimportFoundationvarCFString"Hello,World"//建立CFString字符串varStringasString//將CFString字符串轉換爲Swift原生字符串StringvarCFString//將Swift原生字符串String轉換爲CFString字符串

cfstr1:=   
str:= cfstr1    cfstr2:= str            

這個轉換過程當中Core Foundation類型轉換爲Swift原生類型是須要強制類型轉換的。安全

——Core Foundation框架以內存管理

在Swift原生數據類型、Foundation框架數據類型和Core Foundation框架數據類型之間轉換過程當中,雖然是大部分是能夠零開銷橋接,零開銷並不意味着內存什麼都不用管。Swift類型內存管理是採用ARC,Foundation類型和Core Foundation類型內存管理都是採用MRC或ARC,Core Foundation類型內存管理是基於C語言風格的,它有一個對象全部權的概念。
Objective-C的MRC內存管理
Core Foundation的內存管理與Objective-C的MRC內存管理密不可分,先介紹一下Objective-C的MRC內存管理。
全部Objective-C類都繼承NSObject類,每一個NSObject對象都有一個內部計數器,這個計數器跟蹤對象的引用次數,被稱爲「引用計數」(Reference Count,簡稱RC)。當對象被建立時候,引用計數爲1。爲了保證對象的存在,能夠調用retain方法保持對象,retain方法會使其引用計數加1,若是不須要這個對象能夠調用release或autorelease方法,release或autorelease方法使其引用計數減1。當對象的引用計數爲0的時候,系統運行環境纔會釋放對象內存。
引用計數示例如圖所示,首先在第①步調用者A中建立了一個NSObject對象,這時該對象引用計數爲1。在第②步調用者B中想使用這個NSObject對象,因而使用NSObject對象引用,可是爲了防止使用過程當中NSObject對象被釋放,能夠調用retain方法使引用計數加1,這時引用計數爲2。在第③步調用者A中調用release或autorelease方法,使引用計數減1,這時引用計數爲1。在第④步調用者C中調用release或autorelease方法,只是得到NSObject對象引用,並無調用retain、release或autorelease方法,所以沒有引發引用計數的變化。在第⑤步調用者B中調用release或autorelease方法使引用計數減1,這時引用計數爲0。這個時候NSObject對象就內存就能夠釋放了。

來總結一下:多線程

  1. 誰建立或拷貝對象,他也必定要負責調用NSObject對象release或autorelease方法,使引用計數減1,如圖中調用者A在第①步,負責建立了NSObject對象,那麼調用者A也必須是負責使引用計數減1,見第④步。
  2. 誰調用retain方法使引用計數加1,它也必定要負責調用NSObject對象release或autorelease方法,使引用計數減1,如圖中調用者B在第②步,調用者B調用NSObject對象retain方法使引用計數加1,那麼調用者B也必須是負責使引用計數減1,見第⑤步。
    對象全部權
    一個對象能夠有一個或多個全部者,從全部者的角度看是對這個對象具備了「全部權」,從上圖中看,調用者A和調用者B是全部者,他們多是一段程序,多是一個對象。他們對NSObject對象具備全部權,再也不使用時候他們應該負責放棄對象全部權,當對象沒有全部者時,引用計數爲0,它才能夠被釋放。
    如上圖若是按照對象全部權解釋:調用者A建立或拷貝NSObject對象,這時調用者A就具備了NSObject對象的全部權,見第①步。調用者B調用NSObject對象retain方法,就得到了也NSObject對象的全部權,見第②步。調用者A調用NSObject對象release方法,放棄NSObject對象的全部權,見第③步。調用者C只是使用NSObject對象沒有得到NSObject對象的全部權,見第④步。調用者B調用NSObject對象release方法,放棄NSObject對象的全部權,見第⑤步,可是調用者B使用這個NSObject對象過程當中,因爲其餘調用者放棄全部權,致使NSObject對象被釋放,那麼調用者B中程序就會發生運行期錯誤。

——Core Foundation框架以內存託管對象與非託管對象

Swift中調用Core Foundation函數得到對象時候,對象分爲:內存託管對象和內存非託管對象。閉包

·內存託管對象
內存託管對象就是由編譯器幫助管理內存,咱們不須要調用CFRetain函數得到對象全部權,也不須要調用CFRelease函數放棄對象全部權。
得到這些內存託管對象的方法,是採用了CF_RETURNS_RETAINED或CF_RETURNS_NOT_RETAINED註釋聲明架構

func CFStringCreateWithCString(_ alloc: CFAllocator!, 
_ cStr: UnsafePointer<Int8>,
_ encoding: CFStringEncoding)CFString//內存託管對象->!   
func CFHostCreateCopy(_ alloc: CFAllocator?,
_ host: CFHost)UnmanagedCFHost//內存非託管對象-><>       

·內存非託管對象
內存非託管對象就是內存須要程序員本身管理。這是因爲在得到對象的方法中沒有使用CF_RETURNS_RETAINED或CF_RETURNS_NOT_RETAINED註釋聲明,編譯器沒法幫助管理內存。在具體使用時候咱們能夠上一節的方法判斷是否爲非內存託管對象。
內存非託管對象使用起來有些麻煩,要根據得到全部權方法,進行相應的處理。框架

  1. 若是一個函數名中包含Create或Copy,則調用者得到這個對象的同時也得到對象全部權,返回值Unmanaged<T>須要調用takeRetainedValue()方法得到對象。調用者再也不使用對象時候,Swift代碼中須要調用CFRelease函數放棄對象全部權,這是由於Swift是ARC內存管理的。
  2. 若是一個函數名中包含Get,則調用者得到這個對象的同時不會得到對象全部權,返回值Unmanaged<T>須要調用takeUnretainedValue()方法得到對象。

——Cocoa Touch設計模式及應用之單例模式

什麼是設計模式。設計模式是在特定場景下對特定問題的解決方案,這些解決方案是通過反覆論證和測試總結出來的。實際上,除了軟件設計,設計模式也被普遍應用於其餘領域,好比UI設計和建築設計等。
下面來介紹Cocoa Touch框架中的設計模式中的單例模式。
單例模式
單例模式的做用是解決「應用中只有一個實例」的一類問題。在Cocoa Touch框架中,有UIApplication、NSUserDefaults和NSNotificationCenter等單例類。另外,NSFileManager和NSBundle類雖然屬於Cocoa框架的內容,但也能夠在Cocoa Touch框架中使用(Cocoa框架中的單例類有NSFileManager、NSWorkspace和NSApplication等)。
問題提出
在一個應用程序的生命週期中,有時候只須要某個類的一個實例。例如:當iOS應用程序啓動時,應用的狀態由UIApplication類的一個實例維護,這個實例表明了整個「應用程序對象」,它只能是一個實例,其做用是共享應用程序中的一些資源、控制應用程序的訪問,以及保持應用程序的狀態等。
解決方案
單例模式的實現有不少方案,蘋果公司在《Using Swift with Cocoa and Objective-C》官方文檔中給出了一種單例模式的實現。最簡單形式代碼以下:ide

class Singleton {函數

    static let sharedInstance = Singleton()

}

上述代碼採用static的類屬性實現單例模式,這種類屬性只被延遲加載執行一次,即使是在多線程狀況下也只是執行一次,而且保證是線程安全的。
若是須要進行一些初始化,可使用以下帶有閉包形式代碼:

class Singleton {

    static let sharedInstance: Singleton = {

        let instance = Singleton()

        // 初始化處理

        return instance

    }()

}

——Cocoa Touch設計模式及應用之目標與動做

目標(Target)與動做(Action)是iOS和OS X應用開發的中事件處理機制。

要實現目標與動做的鏈接有兩種方式:Interface Builder連線實現和編程實現。

  1. Interface Builder連線實現
    Interface Builder連線實現就是故事板或Xib文件中,經過連線而現實。
  2. 編程實現
    編程實現是經過UIControl類addTarget(_:action:forControlEvents:)方法實現的,主要代碼以下:

class ViewController: UIViewController {

 

    override func viewDidLoad() {

    super.viewDidLoad()

 

    self.view.backgroundColor = UIColor.whiteColor()

 

    let screen = UIScreen.mainScreen().bounds;

    let labelWidth:CGFloat = 90

    let labelHeight:CGFloat = 20

    let labelTopView:CGFloat = 150

    let label = UILabel(frame: CGRectMake((screen.size.width

             -labelWidth)/2 , labelTopView, labelWidth, labelHeight))

 

    label.text = "Label"

    //字體左右劇中

    label.textAlignment = .Center

    self.view.addSubview(label)

 

    let button = UIButton(type: UIButtonType.System)// 建立UIButton對象

    button.setTitle("OK", forState: UIControlState.Normal)   

 

    let buttonWidth:CGFloat = 60

    let buttonHeight:CGFloat = 20

    let buttonTopView:CGFloat = 240

 

    button.frame = CGRectMake((screen.size.width

         - buttonWidth)/2 , buttonTopView, buttonWidth, buttonHeight)

 

    button.addTarget(self, action: "onClick:",

                     forControlEvents: UIControlEvents.TouchUpInside)

 

    self.view.addSubview(button)   

        }

 

    func onClick(sender: AnyObject) {   

        NSLog("OK Button onClick.")

    }   

        ...

}

上述代碼中建立並設置UIButton對象,其中建立UIButton對象,參數type是設置按鈕的樣式,UIButton樣式:

  • Custom。自定義類型。若是不喜歡圓角按鈕,可使用該類型。
  • System。系統默認屬性,表示該按鈕沒有邊框,在iOS 7以前按鈕默認爲圓角矩形。
  • Detail Disclosure。細節展現按鈕,主要用於表視圖中的細節展現。
  • Info Light和Info Dark。這兩個是信息按鈕,樣式上與細節展現按鈕同樣,表示有一些信息須要展現,或有能夠設置的內容。
  • Add Contact。添加聯繫人按鈕
  • 代碼調用addTarget(_:action:forControlEvents:)方法,方法第一個參數是target,即事件處理對象,本例中是self;方法第二個參數是action,即事件處理對象中的方法,
    代碼中是"onClick:",方法第三個參數是事件,TouchUpInside事件是按鈕的觸摸點擊事件。
    若是調用以下無參數方法:

func onClick() {
}

調用代碼以下:

button.addTarget(self, action: "onClick",

                Ê    forControlEvents: UIControlEvents.TouchUpInside)

區別在於action參數"onClick"方法名不一樣,action參數方法名的冒號暗示了方法名應該具備幾個參數。若是要調用的方法是以下3個參數形式:

func onClick(sender: AnyObject, forEvent event: UIEvent) {

}

那麼調用代碼以下:

button.addTarget(self, action: "onClick:forEvent:",

                Ê    forControlEvents: UIControlEvents.TouchUpInside)

其中"onClick:forEvent:"是調用方法名,onClick表示方法名也是,forEvent表示第二個參數的外部參數名。

——Cocoa Touch設計模式及應用之選擇器

實現目標與動做關聯使用UIControl類addTarget(_:action:forControlEvents:)方法,示例代碼以下:

button.addTarget(self, action: "onClick:",

             forControlEvents: UIControlEvents.TouchUpInside)

其中的action參數"onClick:"事實上就是選擇器(Selector)。

經過選擇器調用方法,關鍵是方法名字,它有必定規律的。窮其根本是源自於Objective-C多重參數方法命名規律。方法名的冒號暗示了方法名應該具備幾個參數,下面咱們看幾個示例:

    //選擇器爲"onClick:"

    func onClick(sender: AnyObject) {

         NSLog("onClick:")

    }

 

    //選擇器爲"onClick:forEvent:"

    func onClick(sender: AnyObject, forEvent event: UIEvent) {   

          NSLog("onClick:forEvent:")

    }

 

    //選擇器爲"onClickWithExtSender:forEvent:"

    func onClick(extSender sender: AnyObject, forEvent event: UIEvent) {

          NSLog("onClickWithExtSender:forEvent:")

    }

出於數據封裝的須要,咱們會在方法前面加private,使其變爲私有方法,代碼以下。

    private func onClick(sender: AnyObject) {

          NSLog("onClick:")

    }

可是這樣方法在調用時候會出現以下錯誤:
unrecognized selector sent to instance 0x7f7f81499b10'

這個錯誤的意思是沒有找到選擇器所指定的方法,也就是沒有找到onClick:方法。正確的作法是在方法前面添加@objc屬性註釋,這說明選擇器是在objc runtime運行環境下調用的。

    //選擇器爲"onClick:"

    @objc private func onClick(sender: AnyObject) {

           NSLog("onClick:")

    }

——Cocoa Touch設計模式及應用之通知機制

通知(Notification)機制是基於觀察者(Observer)模式也叫發佈/訂閱(Publish/Subscribe)模式,是 MVC( 模型-視圖-控制器)模式的重要組成部分。

在軟件系統中,一個對象狀態改變也會連帶影響其餘不少對象的狀態發生改變。可以實現這一需求的設計方案有不少,但可以作到複用性強且對象之間匿名通訊的,觀察者模式是其中最爲適合的一個。

通知機制能夠實現「一對多」的對象之間的通訊。如圖所示,在通知機制中對某個通知感興趣的全部對象均可以成爲接收者。首先,這些對象須要向通知中心(NSNotificationCenter)發出addObserver消息進行註冊通知,在投送對象經過postNotificationName消息投送通知給通知中心,通知中心就會把通知廣播給註冊過的接收者。全部的接收者都不知道通知是誰投送的,更不關心它的細節。投送對象與接收者是一對多的關係。接收者若是對通知再也不關注,會給通知中心發出removeObserver消息註銷通知,之後再也不接收通知。

——Cocoa Touch設計模式及應用之MVC模式

MVC(Model-View-Controller,模型-視圖-控制器)模式是至關古老的設計模式之一,它最先出如今Smalltalk語言中。如今,不少計算機語言和架構都採用了MVC模式。

MVC模式概述
MVC模式是一種複合設計模式,由 「觀察者」(Observer)模式、「策略」(Strategy)模式和「合成」(Composite)模式等組成。MVC模式由3個部分組成,如圖所示,這3個部分的做用以下所示。
· 模型。保存應用數據的狀態,迴應視圖對狀態的查詢,處理應用業務邏輯,完成應用的功能,將狀態的變化通知視圖。
· 視圖。爲用戶展現信息並提供接口。用戶經過視圖向控制器發出動做請求,而後再向模型發出查詢狀態的申請,而模型狀態的變化會通知給視圖。
· 控制器。接收用戶請求,根據請求更新模型。另外,控制器還會更新所選擇的視圖做爲對用戶請求的迴應。控制器是視圖和模型的媒介,能夠下降視圖與模型的耦合度,使視圖和模型的權責更加清晰,從而提升開發效率。

 

對應於哲學中的「內容」與「形式」, 在MVC模型中,模式是「內容」,它存儲了視圖所須要的數據,視圖是「形式」,是外部表現方式,而控制器是它們的媒介。
Cocoa Touch中的MVC模式
上面咱們討論的是通用的MVC模式,而Cocoa和Cocoa Touch框架中的MVC模式與傳統的MVC模式略有不一樣,前者的模型與視圖不能進行任何通訊,全部的通訊都是經過控制器完成的,如圖所示。

 

在Cocoa Touch框架的UIKit框架中,UIViewController是全部控制器的根類,如UITableViewController、UITabBarController和UINavigationController。UIView是視圖和控件的根類。

——Cocoa Touch設計模式及應用之響應者鏈與觸摸事件

應用與用戶進行交互,依賴於各類各樣的事件。事件響應者對象是能夠響應事件並對其進行處理的對象,響應者鏈是由一系列連接在一塊兒的響應者組成的。響應者鏈在事件處理中是很是重要的,響應者鏈能夠把用
戶事件路由給正確的對象。

響應者對象與響應鏈
UIResponder是全部響應者對象的基類,它不只爲事件處理,並且也爲常見的響應者行爲定義編程接口。UIApplication、UIView(及其子類,包括UIWindow)和UIViewController(及其子類)都直接或間接地繼承自UIResponder類。

 

第一響應者是應用程序中當前負責接收觸摸事件的響應者對象(一般是一個UIView對象)。UIWindow對象以消息的形式將事件發送給第一響應者,使其有機會首先處理事件。若是第一響應者沒有進行處理,系統就將事件(經過消息)傳遞給響應者鏈中的下一個響應者,看看它是否能夠進行處理。
響應者鏈是一系列連接在一塊兒的響應者對象,它容許響應者對象將處理事件的責任傳遞給其餘更高級別的對象。隨着應用程序尋找可以處理事件的對象,事件就在響應者鏈中向上傳遞。響應者鏈由一系列「下一個響應者」組成。
1.第一響應者將事件傳遞給它的視圖控制器(若是有的話),而後是它的父視圖。
2.相似地,視圖層次中的每一個後續視圖都首先傳遞給它的視圖控制器(若是有的話),而後是它的父視圖。
3.最上層的容器視圖將事件傳遞給UIWindow對象。
4.UIWindow對象將事件傳遞給UIApplication單例對象。

觸摸事件
觸摸(UITouch)對象表示屏幕上的一個觸摸事件,訪問觸摸是經過UIEvent對象傳遞給事件響應者對象的。觸摸對象有時間和空間兩方面。
1.時間方面
時間方面信息稱爲階段(phase),表示觸摸是否剛剛開始、是否正在移動或處於靜止狀態,以及什麼時候結束,也就是手指什麼時候從屏幕擡起。
在給定的觸摸階段中,若是發生新的觸摸動做或已有的觸摸動做發生變化,則應用程序就會發送這些消息。

  • 當一個或多個手指觸碰屏幕時,發送touchesBegan:withEvent:消息。
  • 當一個或多個手指在屏幕上移動時,發送touchesMoved:withEvent:消息。
  • 當一個或多個手指離開屏幕時,發送touchesEnded:withEvent:消息。

2.空間方面
觸摸點對象還包括當前在視圖或窗口中的位置信息,以及以前的位置信息(若是有的話)。下面的方法是能夠得到觸摸點所在窗口或視圖中的位置。

    func locationInView(_ view: UIView?) -> CGPoint

得到前一個觸摸點所在窗口或視圖中的位置信息:

func previousLocationInView(_ view: UIView?) -> CGPoint

——Swift與Objective-C混合編程之語言

在Swift語言出現以前,開發iOS或OS X應用主要使用Objective-C語言,此外還可使用C和C++語言,可是UI部分只能使用Objective-C語言。

選擇語言
Swift語言出現後,蘋果公司給程序員提供了更多的選擇,讓這兩種語言並存。既然是並存,咱們就有4種方式能夠選擇:

  • 採用純Swift的改革派方式;
  • 採用純Objective-C的保守派方式;
  • 採用Swift調用Objective-C的左傾改良派方式;
  • 採用Objective-C調用Swift的右傾改良派方式。

文件擴展名

在Xcode等工具開發iOS或OS X應用能夠編寫多種形式的源文件,本來就可使用Objective-C、C和C++語言,Swift語言出現後源文件的形式更加多樣。可能的文件擴展名說明:

 

——Swift與Objective-C混合編程之Swift與Objective-C API映射

Swift與Objective-C API映射

在混合編程過程當中Swift與Objective-C調用是雙向的,因爲不一樣語言對於相同API的表述是不一樣的,他們之間是有某種映射規律的,這種API映射規律主要體如今構造函數和方法兩個方面。

一、構造函數映射
在Swift與Objective-C語言進行混合編程時,首先涉及到調用構造函數實例化對象問題,不一樣語言下構造函數表述形式不一樣,如圖是蘋果公司官方API文檔,描述了NSString類的一個構造函數。

 

Swift構造函數除了第一個參數外,其它參數的外部名就是選擇器對應部分名。規律的其它細節圖中已經解釋的很清楚了,這個規律反之亦然,這裏再也不贅述。
2、方法名映射

在Swift與Objective-C語言進行混合編程時,不一樣語言下方法名錶述形式也是不一樣的,如圖是蘋果公司官方API文檔,描述了NSString類的rangeOfString:options:range:方法。

選擇器第一個部分rangeOfString做爲方法名,通常狀況下Swift方法第一個參數的外部參數名是要省略的,「_」符號表示省略。以後的選擇器各部分名(如:options和range),做爲外部參數名。除了參數名對應爲,參數類型也要對應下來。

Swift 2.0以後方法能夠聲明拋出錯誤,這些能拋出錯誤的方法,不一樣語言下方法名錶述形式如圖下圖所示,是writeToFile:atomically:encoding:error:蘋果公司官方API文檔。

比較兩種不一樣語言,咱們會發現error參數在Swift語言中再也不使用,而是在方法後添加了throws關鍵字。
這種映射規律不只僅只適用於蘋果公司官方提供的Objective-C類,也適用於本身編寫的Objective-C類。

——Swift與C/C++混合編程之數據類型映射

若是引入必要的頭文件,在Objective-C語言中可使用C數據類型。而在Swift語言中是不能直接使用C數據類型,蘋果公司爲Swift語言提供與C語言相對應數據類型。這些類型主要包括:C語言基本數據類型和指針類型。

如表所述是Swift數據類型與C語言基本數據類型對應關係表。

Swift語言中的這些數據類型與Swift原生的數據類型同樣,本質上都是結構體類型。

如表所述是Swift數據類型與C語言指針數據類型對應關係表。

從表可見針對C語言多樣的指針形式,Swift主要經過提供了三種不安全的泛型指針類型:UnsafePointer<T>、UnsafeMutablePointer<T>和AutoreleasingUnsafeMutablePointer<T>。T是泛型佔位符,表示不一樣的數據類型。另外,還有COpaquePointer類型是Swift中沒法表示的C指針類型。
下面咱們分別介紹一下。

    1. UnsafePointer<T>
      UnsafePointer<T>是一個比較經常使用的常量指針類型,這種指針對象須要程序員本身手動管理內存,即須要本身申請和釋放內存。它通常是由其餘的指針建立。它的主要的構造函數有:
      · init( other: COpaquePointer)。經過COpaquePointer類型指針建立。
      · init<U>(
      from: UnsafeMutablePointer<U>)。經過 UnsafeMutablePointer類型指針建立。
      · init<U>(_ from: UnsafePointer<U>)。經過UnsafePointer類型指針建立。
      UnsafePointer<T>主要的屬性:
      · memory。只讀屬性,它可以訪問指針指向的內容。
      UnsafePointer<T>主要的方法:
      · successor() -> UnsafePointer<T>。得到指針指向的下一個內存地址的內容。
      · predecessor() -> UnsafePointer<T>。得到指針指向的上一個內存地址的內容。
    2. UnsafeMutablePointer<T>
      UnsafeMutablePointer<T>是一個比較經常使用的可變指針類型,這種指針對象須要程序員本身手動管理內存,本身負責申請和釋放內存。可變指針能夠由其餘的指針建立,也能夠可變指針經過alloc(:)方法申請內存空間,再調用initialize(:)方法初始化指針指向數值。當指針對象釋放時候須要調用destroy()方法銷燬指針指向對象,它是initialize(:)方法的反向操做,他們兩個方法在代碼中應該成對出現的。最後還要調用dealloc(:)方法釋放指針指向的內存空間,它是alloc(_:)方法的反向操做,這兩個方法在代碼中也應該成對出現。
    3. AutoreleasingUnsafeMutablePointer<T> AutoreleasingUnsafeMutablePointer<T>被稱爲自動釋放指針,在方法或函數中聲明爲該類型的參數,是輸入輸出類型的,在調用方法或函數過程當中,參數先首先被拷貝到一個無全部權的緩衝區,在方法或函數內使用的這個緩衝區,當方法或函數返回時,緩衝區數據從新寫回到參數。這是我在學Swift整理的基礎筆記,但願給更多剛學IOS開發者帶來幫助,在這裏博主很是感謝你們的支持!到這裏就基本完成了Swift語言基礎筆記整理了。  若是你們以爲此博文對您有幫助,那就動動你的小手指點個贊!!   哈哈,感謝各位博友的支持!!!
相關文章
相關標籤/搜索