Swift
常量和變量
-
var
定義變量,設置之后可以修改 -
let
定義常量,設置之后不可以修改 - 語句末尾不用使用
;
- 在 Swift 中使用
print()
替代 OC 中的NSLog
,print
的性能更好 - 用
let
定義常量,該常量的內(nèi)存地址不允許修改,但是可以修改其內(nèi)部的屬性
- 常量&變量的使用原則:初學的時候,盡量先用
let
家乘,只有需要變的時候寂纪,再用var
防症,能夠更加安全
- 初次接觸
Swift
中會因為簡單的var
let
誤以為Swift
中的類型非常松,其實所有變量的準確類型都是在賦值的同時自動推導的 -
Swift
是對類型要求非常嚴格的一門語言,一個值永遠不會被自動轉(zhuǎn)換成其他類型,如果要轉(zhuǎn)換,必須顯示轉(zhuǎn)換
//常量不可以改變
let number = 10;
//變量
var number1 = 10;
number1 = 20;
//Swift可以自行做類型推斷
print(number)
//定義變量(如果指定類型,一定要顯性的)
var name:String = "shkljsjd"
var age:Int = 12;
var height:Float = 180.5
var 體重:Double = 12.2
var gender:Bool = true
var sex: Character = "m"
var telephone = "123456789"
//類型轉(zhuǎn)換
let 整型體重 = Int(height)
print(整型體重)
var 整型電話 = Int(telephone)!
print(整型電話)
字符串
使用String
的原因
-
String
是一個結(jié)構體,性能更高-
String
目前具有了絕大多數(shù) NSString 的功能 -
String
支持直接遍歷
-
-
NSString
是一個OC
對象,性能略差 -
Swift
提供了String
和NSString
之間的無縫轉(zhuǎn)換
- 在Swift中絕大多數(shù)的情況下,推薦使用 String 類型
//遍歷字符串
let str = "qwerasdf"
for s in str {
print(s)
}
//獲取字符串的長度
print(str2.characters.count)
// 字符串快速拼接
let str1 = "zhangsan"
let str2 = "lisi"
let i = 10
print(str1 + str2)//可以理解成數(shù)組
print("\(str1) \(str2) \(i)")//這里可以使用\(變量名)的方式快速拼接字符串
//字符串的拼接
//這里是swift中的字符串(非常非常費勁)的拼接方法
let str: String = "zhangwu"
var subStr = str.substringWithRange(Range<String.Index>(start: str.startIndex, end: str.endIndex))
str.insert("1", atIndex: str2.startIndex.advancedBy(3))
//所以一把建議把swift里面的字符串轉(zhuǎn)換成NSString進行拼接(刪除方法同理)
let str3: NSString = "zhangsanwangwu"
print(str3.substringWithRange(NSMakeRange(0, 3)))
// 格式化字符串(這里提供了一種和OC中的stringWithFormat一樣的方法,需要注意的后面的arguments是一個數(shù)組,即使一個變量也要放入數(shù)組中)
for _ in 0...10 {
let str = String(format: "zhangsan - %04d", arguments: [arc4random_uniform(100)])
print(str)
}
數(shù)組,字典,元組
數(shù)組
- 如果定義數(shù)組時指定了保存對象的類型山叮,擇不能向數(shù)組中添加其他類型的內(nèi)容
-
let
定義的數(shù)組是不可變的
-
var
定義的數(shù)組是可變的
// 數(shù)組中保存的都是字符串
let arr = ["zhangsan", "lisi"]
// 數(shù)組中保存的是 NSObject
let arr1 = ["zhangsan", 1]
// 添加元素
array.append("lisi")
//更新
array[0] = "zhangwu"
// 刪除元素
array.removeAtIndex(1)
// 拼接數(shù)組
var array2 = [String]()
array2.append("1")
array2.append("2")
array += array2
字典
// 定義并實例化字典(這種類型是開發(fā)中常用的類型)
var dict = [String: AnyObject]()
//添加(更新)
dict["name"] = "zhangsan"
dict["age"] = 18
// 刪除
dict.removeValueForKey("age")
// 合并字典
var dict2 = ["name": "wangwu", "age": 80, "title": "boss"]
for (k, v) in dict2 {
dict.updateValue(v, forKey: k)
}
元組
//元組(tuple)(可以放任意類型)
//不定義標記
let student = ("1",1,1.1,[1],[1:1])
//訪問元組元素
print(student.4)
//定義標記
let student1 = (姓名:"小明",性別:"W",年齡:[19,12,20])
//訪問元組元素
print(student1.年齡[1])
print(student1.2[1])
- 總結(jié) :
- 數(shù)組[index,value]:里面放著兩種屬性,一種是索引,一種是元素,數(shù)組中放著的只有元素,我們可以通過索引找到元素
- 字典[key,value]:和oc中一樣都放著鍵值對,可以通過key訪問value
- 元祖[標記,value]:可以看做是數(shù)組和字典的結(jié)合體,里面的標記可以不定義(默認像數(shù)組中的index),可以定義(就像字典中的key,但是字典中的key是有類型的,標記是無類型的)
循環(huán),遍歷,switch,枚舉
循環(huán)和遍歷
//whlie
while false
{
}
//類似于do...while
repeat
{
}while false
// 循環(huán)
for var i = 0; i < 10; i++ {
print(i)
}
// 遍歷 0 ~ 9(省略號之間不能有空格)
for i in 0..<10 {
print(i)
}
// 遍歷 0 ~ 10(省略號之間不能有空格)
for i in 0...10 {
print(i)
}
// 特殊寫法(如果不關心循環(huán)本身的索引,可以用通配符'_'忽略)
for _ in 0...10 {
print("hello")
}
//數(shù)組的遍歷
var studentArr = [1,2,3,4,5,6,7,8,9]
for item in studentArr
{
print("item = \(item)")
}
//可以遍歷數(shù)組中的所以和元素(間接用到了元組的特性)
for(index,value)in studentArr.enumerate()
{
print("index =\(index) value = \(value)")
}
//字典的遍歷(同樣間接用到了元組的特性)
var studentDic = ["姓名":"張三","愛好":"男"?"]
for (key,value)in studentDic
{
print("key = \(key) value = \(value)")
}
switch和枚舉
//swtich(自帶break,可以重復,但是找到一個就不會找第二個)
var name1 = "小明"
switch name1
{
case "小明":print(name1)
//要想要自帶貫穿效果(重復之后也繼續(xù)尋找)加fallthrough關鍵字
fallthrough
case "小明":print(name1)
//一定要包含所有條件
default: print("不存在")
}
//case可以寫區(qū)間
var age1 = 12
switch age1 {
case 10...15:
print("a")
default:
print("默認")
}
//當age2 == 15成立的時候把age2賦給age
var age2 = 15
switch age2{
case let age where age2 == 15:
print("age = \(age)")
default: break
}
//遍歷元祖
var studentTuple = (姓名:"張三",性別:"男",年齡:12)
switch studentTuple
{
case ("張三","男",12):
print("找對了")
case (_,_,12):
print("找對了")//只要一個條件成立就可以進
default:
break
}
//枚舉(和oc一樣默認初始值是0,如果修改初始值的話需要制指定類型,swift的枚舉創(chuàng)建必須要帶case)
enum season :Int
{
case spring = 2
case summer
case autumn
case winter
}
print(season.autumn)
//打印枚舉值的值
print(season.autumn.rawValue)
var today = season.summer
//篩選枚舉
switch today
{
case.spring:print("春天")
case.summer:print("夏天")
case.autumn:print("秋天")
case.winter:print("冬天")
}
//枚舉也可以這樣定義(case后面跟著多個元素,枚舉值的類型也可以是String類型)
enum City:String
{
case 北京 = "北京",上海
case 石家莊,武漢
case 青島
}
函數(shù)
//函數(shù)
//無參無返回
func func1()
{
print("無參無返回值")
}
//無參有返回
func func2()->String
{
print("無參有返回值")
return "小明"
}
//有參無返回
func func3 (a :String)
{
print("有參無返回值")
}
//有參有返回
func func4 (a:Int)->String
{
print("有參有返回值")
return String(a)
}
//函數(shù)調(diào)用
func1()
func2()
func3("123")
func4(1)
//不定參數(shù)(這點與oc中的不大一樣,如果傳入的參數(shù)不固定可以這樣寫)
func add(a:Int...)->Int
{
var result = 0
for item in a
{
result += item
}
return result
}
//調(diào)用的時候傳入的參數(shù)就是不固定的
print(add(1,2,3,4))
//返回值是多個參數(shù)
func func5()->(Int,String)
{
return(1,String(123))
}
//交換
var m = 1
var n = 2
//變成指針(inout)(只有改變指針才能達到換值的目的)
//xy是外部參數(shù),ab是內(nèi)部參數(shù),系統(tǒng)默認第一個不會幫我們省略,以后的參數(shù)會幫我們省略,所以要將x寫出來,但是y可以省略
func change(inout x a:Int,inout y b:Int)
{
let temp = a
a = b
b = temp
}
change(x: &m, y: &n)
結(jié)構體和類
- Swift要求類和結(jié)構體中的存儲屬性(非lazy)在對象初始化完畢后必須有值
結(jié)構體
- Swift里面的結(jié)構體和oc中的不太一樣,蘋果官方更推薦在開發(fā)中使用結(jié)構體,Swift中的結(jié)構體更像類,可以定義屬性和方法
- Swift中的結(jié)構體是值類型,也就是說在賦值的時候是拷貝一塊內(nèi)存空間,類似于oc中的深拷貝
- Swift中的結(jié)構體不可以繼承
struct Father
{
init ()
{
print("______")
}
}
//結(jié)構體
struct Person{
//存儲屬性(和@property一樣)
var name:String!
var age:NSInteger!
//計算屬性(不會存值,依賴于其他存儲屬性,沒有存儲空間)
var fatherAge:NSInteger
{
set {
age = newValue - 20
}
get {
return age + 20
}
}
//初始化方法
init()
{
print("初始化方法")
}
//自定義初始化方法
init(name:String,age:NSInteger)
{
self.name = name
self.age = age
}
//懶加載屬性(用到時在加載)
lazy var father:Father = Father()
//類屬性
static var Arr = Array<Int>()
//對象方法
func eat(){
print("吃飯")
}
//類方法
static func happy() {
print("類方法happy")
}
}
類
- 類可以繼承
- 類是引用類型,賦值的過程是復制的指針,兩個對象同時指向同一塊內(nèi)存空間,修改一個影響另一個,類似于淺拷貝
class Person1:NSObject
{
//重寫父類的方法必須用關鍵字override
override init()
{
print("初始化人")
}
}
class dog: NSObject
{
//存儲屬性
var name:NSString!
var age:NSInteger!
//計算屬性
var fatherAge:NSInteger{
set{
age = newValue / 10
}
get {
return age * 10
}
}
//懶加載屬性
lazy var person:Person1 = Person1()
//類屬性
static var arr = Array<Int>()
//類方法 (class和static都可以創(chuàng)建類方法,唯一的區(qū)別是用static修飾的類,其子類不可以重寫該類的方法)
static func eat()
{
print("吃")
}
//對象方法
func happy()
{
print("happy")
}
//自定義初始化方法
init(name:String,age :NSInteger)
{
self.name = name
self.age = age
}
}
protocol和extension
- 在swift中協(xié)議和oc的區(qū)別不是很大,而extension更像是oc中的category,extension不但可以給類擴展,也可以給協(xié)議擴展
protocol
- swift中的協(xié)議把可選協(xié)議個必須實現(xiàn)的協(xié)議分開
//必須實現(xiàn)的協(xié)議
protocol PersonDelegate
{
//對象方法
func numberOfDog()->String
// 類方法
static func numberOfDog()
//屬性
var gender:String{get set}
//類屬性
static var classRoom:String{ get set}
}
//可選協(xié)議
@objc protocol DogDelegate{
optional var name:String{set get }
//方法
optional func eat()->String
}
extension
- 正因為swift中的extension有這個特性,所以開發(fā)過程中我們可以充分利用extension的特性可以把我們的項目模塊化(例如創(chuàng)建tableView的時候,兩個代理可以用extension寫出來)
//擴展
extension Person {
func text (){
print("asda")
}
}
//創(chuàng)建一個類
class Student:NSObject
{
var delegate:DogDelegate?
override init() {
super.init()
self.delegate = self
}
// func eat() -> String {
// return "123"
// }
}
extension Student : DogDelegate
{
func eat() -> String {
return "123"
}
}
閉包
- swift中的閉包類似于oc中的block
- 閉包表達式的類型和函數(shù)的類型一樣(也就是in之前的部分)
- in關鍵字的目的是便于區(qū)分返回值和執(zhí)行語句
- 關于閉包表達式的優(yōu)化
- 1.類型優(yōu)化, 由于函數(shù)中已經(jīng)聲明了閉包參數(shù)的類型, 所以傳入的實參可以不用寫類型
- 2.返回值優(yōu)化, 同理由于函數(shù)中已經(jīng)聲明了閉包的返回值類型,所以傳入的實參可以不用寫類型
- 3.參數(shù)優(yōu)化, swift可以使用$索引的方式來訪問閉包的參數(shù), 默認從0開始
//閉包
var block :(Int->Void)?
//實現(xiàn)
block = {(a:Int) in
return a
}
block!(0)
//第二種寫法(可以省略,$0第一個參數(shù),$1代表第二個參數(shù))
var bb:(Int,String)->String
bb = {
return $1
}
bb(1,"2")
//閉包作為函數(shù)回調(diào)
func eat(block:(a:Int)->(Int))->Int
{
return block(a: 1)
}
eat { (a) -> (Int) in
return a
}