大白话Swift入门
-
!?
?表明可选类型,假如声明属性或变量的话便是默认值为nil的意思,
!表明解包,对加!的在运用 前必定要做判nil处理,一般用if let 和 guard let来判断,或许用 if a != nil 来做判断
-
闭包的运用
闭包的表达式:
{(参数)-> 回来值 in
//代码
}
运用比如
声明为变量:
typealias Swiftblock = (String,Any) -> Void
var testBloc/ V : T r wk: SwiS = V Sftblock?
运用:
testBlock?("ddd","ffffff")
完成:
{ [weak self] (a,b) in
print(a)
print(b)
}
[weak sed 5 P e t x ; ;lf]是为了避免循环引证,(a,b)是传过来的参数
逃逸闭包:
便是闭包作为函数的参数,但是在函数结束今后才. ` O r Q E r去履行这个参数的就叫逃逸闭包,在参数类型前加@escaping
逃逸闭包的Q ` 7 [ @ ) .运用比如
private func requestData(success:@escT i }aping (Any) -> Void) {
DispatchQueue.global().async {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3, execute: {
success("dat5 J v ^ K 7a") //3秒后才履行闭包success
})f j 3 a ~
}
在这个比如中闭包success作为参数,但是他在函数履行完今后过了一段时间才履行,所M w ! p ~ $ g |以他便是逃逸闭包
- Any 和AnyObject 类型的 付值时必定要用W l N I n as! 或 as? 做类型匹配
比如:
requestData { (data) in
let str: String = d2 ^ R K b w raN / | U k t ` Rta as! String //由于data是Any类型的付值给String类型的就需要做类型匹配 ,用as!要确保类型一致且不{ V Y T R为nil
print(str)
//或许用as? 来做类型匹配如下
if let stra = data as? String {
prX z 3 : : V jint(stra)
}
let strb: String = data as? String ?? ""
priM d ( . T }nt(strb)
guard let strc = data as? String else {
return
}
print(strc)
}
func requestData(success:@escaping (Any) -> Void) {
success("da, @ $ & [ wta")
}
上面比如中由于参数data是Any类型的付值给String类型的时分就需要做类型匹配
-
声明函数参数或回来值的时分加?,不然传参数或回来回来值的时分对于可选类型的值要加”!”
-
写署理模式的时分
protocol CCDelegate : class { func doSomething()~ ! 1 o y T 0 p }
记住在后{ H F J H 9 .面加上class关键字,一般加class ,
署理当作变量的时分用weak 润饰避免循环引证
weakk O J P O L z 1 , var delegate:P D ) h : . U k 3 CCDelegate?
-
if let 和 guard let 的用法,一般用来做非空判断
var some: String? if some != nil{ print(some!) } //或许 guard some !=- v / f C z nil else{ return } print(some!) //上面的Y I U判断用 if let 和guard let 如下 if let aSome = some{ print(aSome) } guard let aSome = s{ e bome elL e s _ q L V D Ese { return } print(aSome; 9 R e D)
-
swift单例的运用
单例的一般书写格局
class Sin] ] mgleTest {
static let shared = S# R l ^ L ] ^ingleTestn Z & V J U L l +()
private init() {} //必定要加private避免外部经过init直接创建实例
}
单例的运用比如:
单例类
class SinT s V _gleTest {
var aV9 . t [ J Z ialue: NSString?
var bValue: NSString?
static let shared = Si^ G l p - ngleTest()
private init() {} //必定要加private避免外部经过init直接创建实例
}
单h v y x - 5 P例的运用
SingleTest.sv B J N d [ Qhared.aValue1 ` n Q } g p . = "aaa"
SingleTest.shared.bValue = "bbb"
print("SingleTest.shared.aValue =(SingleTest.shared.aVa- k J blue ?? "kong")")
//输出成n / i & j i果为:SingleTest.shared.aValue =aaa
- .t& e 3 | &ype .self 和 type(of:) 的简略了解
.I d E e R d Otype 是类的类型相当于oc中的Class,
.self 是 静态的在编译时就确定的类 相当于oc中的ca ( b a ^lass
type(of:) 是实例的类 ,相当于oc 中的 class
比如:
let; a u f L Y ` aa = "aaaa"
let stringMetaTy_ Y 0 [ H s 3 Upe:i o p + Z s f * Strinb } t 6g.Type = String.self
let H K v y stringInstanceType: String.Type = type(of: aa)
print("stringMetaType = (stringMf w C ) Y NetaTypen + b)")
prinQ { *t("stringIns % % % + C % * `tanceType = (stringInstanceType)")
if type(of: aa) == String.) i 2self {
print("bbbbbbbb")
}
if type(C ^ zof: aa) is String.Type{
print("cccccc"S } } -)
}
//打印成果如下
stringMetaType = String
stringInstanceType = String
bbbbbbbb
cccccc
从上面的比如能够得到验证
- Swift Pro/ % 9 U * k rtocol 及面向协议编程(POP)的了解
协议的一般书[ , e ` e写格局
protocol TestProtocol {
var testVa} L z , K % w wr: Int {V ^ E { W ! [ get set}
func testFunc()
}
Proh 3 U v v 5 0tocol是约好的W . o I一种协议,协议中能够有变量,和办法,协议便是一种约好,假如某个对象恪守了该约好就要去完成该约好(协议)的办法和变量(假如恪守了就好比是许诺了就得去完成),协议中办法和变量也能够界说为可选(optional)] z s E H x类型的,假如变量或办法是可选q & N 9 ? W I类型的就不需要必定去完成。
协议中办法和变量为可选A & % 0 @的protocol格局如下:
@objc protocol TestProtocol {
@objc options p Y @ f { Kal var testV* b ) & K Z Xar: Int { get set} //可选
//协议中的变量需要指定 get set
@objc optional func testFunc() //可选
func noOptionFunc() //不可选
}
协议的运用
class TestClas: Test/ $ m o VProtoc| + qol {
//完成协, 0 7议TestProtocol中的办法
funk W 7 p x 7 = 6 Rc noOptionFunc() {
print("必定要完成的函数")
}
//完成协议Tes e s zstProtT d d { R 9ocol中的办法
func testFun; J l } Tc() {
prx o Lint("不需要必定完成的函数")` f 2
}
}
protocol中的 associatL } l I – !edtype关键字
associatedtype用来界说一个在协议中的“泛型”类型
界说为 associatedty~ n Y R u Npe类型的在d I W D完成协议的类中运用的时分指明该类型的详细类型是什么就能够了
associatedtype的比如如下
protoc} * $ 4ol TestProtocol {
ast Q ?sociatv U (edtype Num
func testFunc() -> Num
}
cx O P Vlass TestClassInt: TestProtocol {
func testFunc() -> Int {
return 1
}
}
class TestCQ b /lassDouble: TestProtocol {
func testFunc() -> Double {
return. 7 x . - 2 4 9 & 1.666666666
}
}
上面比如 TestProtocol中的 Num 被界说为associatedtype,在 TestClassInt和TestClassDouble中用的时分 把Num别离替换为相应l W 1 x $ g ; G z的IE ; # `nt 和 Double即可
协议的扩展( Protocol Extension):
协议扩展能够给协议内部的函数增加完成以及给协议增加新的函数等,从而将函数功用增加到恪守协议的所有类型中
比如如下:
@objc protocol Person {
@objc optv $ C L | 9 tional var age: Int { get set}
@ob| } qjc optional func work()
}
//Person的a ) E 6 ] ~扩展
extensiow a E c - r A Jn Person {J $ C
func work(){
print("我想上厕所")
}
func run() {
print("我在跑步")
}
}
//Man恪守protocol Person协议
class Man:Person {
var age: Int = 20
func run() {
print("我是男的也在跑步")
}
}
//Woman 恪守pron p ~tocol Person 协议
class Woman: Person {
vau 2 [ V i O I u Sr at D 9 e v 1 yge: Int = 18
func work() {
print("G - P j去女厕所上厕所")
}
}
let man = Man()
man.w] r & l Q E gork()
man.ruV s k V R M .n()
let woman = WomaT 5 p ] en()
woman.work()
woman| 4 * M o ~ e E.run()
//打印成果如下
//我想上厕所
//我是男的也在跑步
//去女厕所上厕所
/{ 9 = 7 W/我在跑步
上面比如便是对协议扩展的应用
面向协议编程+ ? H Y 2 g(POP)的了解
简略了解面向协议编程便是用界说协议来替代面向对象编程中的承继多承继等还能到达运用灵活宽和偶的目的。
@objc protocol Person {
@objc optional var age: Int { get set}
@objcP S c 9 k 9 n 1 optional func w! l p - U zork()
}G a f @
//男性
class Man:Person {
var age: Int = 20
func work() {
printF + Q e r _ 7 G("去男厕所上厕所")
}
}
//女人
class Woman: Person {
var age: Int = 18
func work() {
pr- p 9 t M + bint("去女厕所上厕所")
}
}S % ? M ?
上面7 e H U U J N比如中界说了一个Pej v @ 3 J [ !rson的协议,让Man类和Woman类恪守Person协议就能够到达面向对象编程中承继的效果,假如有多个协议要恪守的话就能够经过恪守多个协议来到达面向对象编程中的多承继的效果
- Swift 初始化函数及便当结构器(convenience)的简略了解
Swiftd . % c Z !的初始化函数有两种一种是指定初始化函数(Designated IniS m n Ktiali_ + czers )便是通常的 init函数,一种是便当初始化函数(Convenience Initializers)便是在init函数前加convenience关键词的初始化函数
Swift对初始化有很严厉的规则要求,我了解如下:
.自己至少要有一个“指定初始化函数”
.便当初始化函数中必须要调用自己的指定初始化函数
.假如有父类要在自己的指定初始化h 8 q A }函数中调用父类的指定初始化函数
比如如下:
创建一个自界说view
class M_ P V x k vyView: UIView {B 6 F K U
private var testvar: String?
//自己的指定初始化函数
override init(frame: CGRect) {
//父类的指定初始化函数
sup0 , x u O L Wer.iniD ` 2 ~t(frame: frame)
}
//界说一个带v o B t j s S + H参数的便当初始化函数
convenience init (param: String){
//便当初始化函数中调用自己的指定初始化函数
self.init(frame{ 6 9 A { ] Z: CGReR k & S act.zero)
//赋值
testvar = param
}
required init?(coder: NSCoder) {
fatalError(W t M g @ m P"init(coder:) has not been implemented")
}
}
运用如下:
//用便当初始化函数初始化一个myView
let myView = MyView(param: "传的参数")f r _ m d | P
上面比如中界说了一个带参数param的便当初始化函数init (param: String),在便当初始化函数中调用了自己的指定初始化函数init(frame:CGRect),在自己的指# T P r A定初始化函数中调用了父类的指定初始化函数super.init(frame:fram% j ] Q } H L 0e)。
上面的比如只是简略的说明晰便当结构函数的用法,一般像本例中的初始化] % W能够不用便当结构函数来完成,用指定初始化函数就能够,指定初始化函数完成的比如如下:
class MyV; b ? J ^ , |iew: UIView {
private var testvar: String?
init (param: String){
super.init(frame: CGRec1 . Z :t.zero)
testvar = param
}
requir - k :ed init?(coder: N% ] U PSCoder^ 8 Q) {
fatalError("init(coder:) has not been implemented")
}
}
运用 指定l 3 W $初始化函数初始化myView
let myView = MyView(param: "传的参数")
- Swift中的高阶函数map,filter,reduce,flatMap的简略了解
map, filter* + 3, reduce,flatMt x ` $ap函数用的是一种函数式编程的思维
map 操作回来的是一个成果数组(调集),该数组(调集)中的元素是对操作前的数s s $ 3 l组中每个元素进行相同操作后构成的新元素
filter操作回来成果是一个数组(调集),该数组(调集)中的元素是操作前数组中符合筛选条$ F a Q件的@ 1 B 9 b元素
reduce操作回来成果是一个值,该) s / = v u T值是用初始值和数组(调集)中的w o [ ] j每个元素调用相同操作来生成的
flatMap回来的是一个数组,这个回来的^ l k e 5 –数组是将多个数组(调集中)的元素放到一个数组中构成的新数组
-
在界说变量的时分尽可能的给个初始值,不然会有一大堆的?要处理,比如如下
class Model: NSObjeF P m !ct { var data: [CellModel] = [CellModel]() var title = "" } clai ~ X h zss CellModel: NSObject { var name = "" var iconImg =2 , l $ d % f k 5 "" var prod0 = 6 w # ! NuctID = "" }
13.元祖(Tuple)
最简略的元组便是在圆括号中,用逗号切割的一组值。比如如下:
var. h % 0 V Q } F tuple =s k d ~ k (100, "哈哈哈", 222)
元祖中的元素带有称号的元祖比如如@ B下:
var tuple = (code: 1000, des: "恳求失利| S } } u T")
元祖有以下特色:
.元祖一旦声明,就v – 2 # m { R M不能再增加/删除其间的元素,但是能够改变元素的值。
.不能更改现已声明的元素称号
元祖的取值
依据声明时元素是否有称号,取值办法分为两种,没有称号的用下标取值,有称号的运用称号取值比如如下:
var aTuple = (1000,"恳求失利") //无称号的
var bB W j _Tuple = (code:1000,des: "恳求失利") //有称号的
print(aTuple.0) // 输出成果: 1000
print(aTuple.1) /e R z (/ 输出成果: "恳求失利"
print(bTuple.code) //输出成果: 1000
print(bTuple.des) //输出成果: "恳求失利"
-
假如是oc和swift混合编程,那么假如想让sS z = # Q nwift类中的属性或办法能被oc访问,就需要在属性或办法的前面加 @obj* 1 / Fc 关键字,比如如下:
@objc var isLog: Bool = true @objc private var dic = Dictionary<String, Any>() @objc func callRequest(){ }
一些基础的总结,有不对的当地还请留言纠正