iOS入门笔记

118 阅读9分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

1.搭建ios开发环境

mac上下载xcode, xcode不同版本,sdk版本不同(可在网页developer里查看)。

从远程github库拉取对应文件夹:

现在本地建立空文件夹,进入文件夹,在终端:

参考:github只clone子目录 (zhuanlan.zhihu.com/p/54581830)

$ git init #初始化

$ git remote add origin  https://github.com/datawhalechina/team-learning-program.git # 增加远端的仓库地址

$ git config core.sparsecheckout true # 设置Sparse Checkout 为true 

$ echo "IOS" >> .git/info/sparse-checkout # 将要部分clone的目录相对根目录的路径写入配置文件

$ git pull origin master #pull下来代码

2.认识swift

支持多编程范式和编译式的开源编程语言,用来撰写基于macOS/OS X、iOS、iPadOS、watchOS和tvOS的软件。

是object-c的升级版,“没有C的Objective-C”

面向协议的新型函数式编程语言

3.基础语法

3.1数据类型

数据定义

let name_1 = 1 // 常量

var name_2 = 2 // 变量



var name_3:String = '333' // 类型注解

var name_4, name_5, name_6: Double // 快速定义多个同类型变量



var cat = 1; print(cat) // 单行用分号分隔语句



// 可嵌套注释

/*

注释1

/* 注释2*/

*/



// 元祖拆包

let http200 = (200, 'ok')

let (statusCode, statusMessage) = http200



// 忽略某个值

let (code, _) = http200



// 下标访问,0开始

let code = http200.0

let message = http200.1



// 可选类型与没有值

var optional_v1: Int? = 404

optional_v1 = nil



/* 隐式解析可选类型:

如果一个变量之后可能变成 nil 的话请不要使用隐式解析可选类型

*/

var optional_v2: Int! = 404 // ?改!,隐式解析可选类型:可以自动解析的可选类型



let int_1 = optional_v1! // 需要加!

let int_2 = optional_v2 // 直接当非可选值用



if optional_v2 != nil { // 判断可选值是否有值

// 用!后缀来取出可选值的值。取之前一定要确认有值, 否则会报错

    print("value: (optional_v2!)") 



}



// 可选绑定:判断可选值是否有值的同时还能取出值(有值的情况),用于if和while语句

if let name_c = Int("123b") { 

    // 在这里,name_c是一个具体值,可以直接用

    

} else {



}

数据类型汇总

bitable copy text

可选值

处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加 ?。如果 ? 之前的值是 nil? 后面的东西都会被忽略,并且整个表达式返回 nil。否则,? 之后的东西都会被运行。在这两种情况下,整个表达式的值也是一个可选值。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")

let sideLength = optionalSquare?.sideLength

字符串

类型:String,Character

Swift 的 StringCharacter 类型完全兼容 Unicode 标准。

每一个 Swift 的 Character 类型代表一个可扩展的字形群。而一个可扩展的字形群构成了人类可读的单个字符,它由一个或多个(当组合时) Unicode 标量的序列组成。

定义与初始化

字符串可根据let和var设置为不可变或可变

值类型,值拷贝,操作字符串或函数传递,会拷贝一个新值,不修改旧值。

// 初始化:默认为空

var s1 = ""               // 空字符串字面量

let s2 = String()  // 初始化方法



var s1: Character = "!"               // 空字符串字面量

let s2 = String()  // 初始化方法



// 遍历string

for c in "dddd" {

    print(c)

}



// unicode,一个字符由多个unicode组合成

let precomposed: Character = "\u{D55C}"    // 한

let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}" //  是 🇺🇸  





// 根据索引获取字符

let greeting = "Guten Tag!"

greeting[greeting.startIndex] // G

greeting[greeting.index(before: greeting.endIndex)] // !

greeting[greeting.index(after: greeting.startIndex)] // u

let index = greeting.index(greeting.startIndex, offsetBy: 7)

greeting[index] // a



// 通过索引范围遍历

for index in greeting.indices {

   print("(greeting[index]) ", terminator: "") // 打印输出“G u t e n   T a g ! ”

}

操作

1.连接:

s1.append()

用+/+=拼接

字符串插值:可以将变量插入字符串

(变量名或表达式)

2.字符串的字符数量

s.count

可扩展的字形群可以由多个 Unicode 标量组成。这意味着不同的字符以及相同字符的不同表示方式可能需要不同数量的内存空间来存储。所以 Swift 中的字符在一个字符串中并不一定占用相同的内存空间数量。因此在没有获取字符串的可扩展的字符群的范围时候,就不能计算出字符串的字符数量。如果你正在处理一个长字符串,需要注意

count 属性必须遍历全部的 Unicode 标量,来确定字符串的字符数量。

3.访问字符串

由于字符串不同字符可能会占用不同数量的内存空间,所以字符串不能用整数做索引,需要字符串从开头遍历每一个unicode标量直到结尾。

s.Index:字符串每个字符的位置。

s.startIndex:第一个字符的索引

s.endIndex:最后一个字符的后一个位置的索引

s.index(before: ):前面一个的索引

s.index(after: ):后面一个的所以

s.index(_:offsetBy:):偏移量的索引

s.indices:创建一个包含全部索引的范围Range

4.修改字符串

插入:

s.insert(_:at:):在一个字符串的指定索引插入一个字符

s.insert(contentsOf:at:):在一个字符串的指定索引插入一个段字符串

删除:

s.remove(at:):在字符串指定索引处删除一个字符

s.removeSubrange(_:):在字符串指定索引删除一个子字符串

5.字符串比较

字符串/字符相等

两个字符串(或者两个字符)的可扩展的字形群集是标准相等,那就认为它们是相等的。只要可扩展的字形群集有同样的语言意义和外观则认为它们标准相等,即使它们是由不同的 Unicode 标量构成。

\u{E9}和\u{65}\u{301}都表示é,它们是相等的。

前缀相等

s.hasPrefix(_:):检查特定前缀

后缀相等

s.hasSuffix(_:):检查特定后缀

访问字符串的值:

利用3种编码格式访问字符串的值:

s.utf8:访问utf-8形式

s.utf16:访问utf-16形式

s.unicodeScalars:访问unicode标量表

集合

集合可被声明为可变var或不可变的let

3种基本集合类型:

Array:同类型有序数据

创建:

// [Int] 等同于Array

特定类型空数组: var arr = Int // 构造语法:类型()

根据上下文可推断类型:var arr = []

带有默认值:var arr = Array(repeating: 0.0, count:3) // 相当于[Double],等价于[0.0, 0.0, 0.0]

两个数组相加得到新数组:var arr = arr1 + arr2

数组字面量:var arr: String = ["1", "2"]

访问:

arr.count:获取数据项数量

arr.isEmpty:检查是否count是否为0

arr[0]:根据整数索引获取值,从0开始

修改:

arr[0] = new_value

arr[1...4] = [x1, x2, x3, x4]

arr.append(_:):增加数据项

arr += [xx]:增加数据项

arr.insert(_:at:):在某个具体索引值前增加数据项

arr.remove(at:):移除特定索引项并返回被删除值

arr.removeLast():删除最后一项

遍历:

for val in arr {

}

// 用枚举的形式获得索引和值

for (index, value) in arr.enumerated() {

}

Set:同类型无序无重复

能被存储在集合的类型,都应可被哈希化。即能够被计算出哈希值(一个Int值)。

比较时根据哈希值确认是否相等。

swift所有基本类型默认可哈希。

创建:

构造器:var st = Set() // Set不像Array,没有简化形式

上下文推断,空set:st = []

数组字面量:var st: Set = ["1", "2", "3"]

字面量显示声明+类型推断:var st: Set = ["2s", "3"]

访问:

st.count:元素数量

st.isEmpty:是否为空

st.contains(_:):是否包含特定值

遍历:

for val in st { // 无序

}

for val in st.sorted() { // 先排序,返回有序数组再遍历

}

修改:

st:insert(_:):插入元素

st.remove(_:):删除元素,删除成功返回被删除元素,否则返回nil

集合运算:

a.intersection(b):交集

a.symmetricDifference(b):并集-交集

a.union(b):并集

a.subtracting(b):a中有,b中无。a去掉交集

比较:

// a.hashValue == b.hashValue

st_a == st_b:判断a和b集合是否包含全部相同的值

st_a.isSubset(of: st_b):a是否是b的子集

st_a.isSuperset(of: houseAnimals):a是否是b的父集合

st_a.isDisjoint(with: cityAnimals):a和b是否无交集,true表示没有交集

Dictionary:无序键值对

定义:

拥有确定类型:var dict = Int: String // [key: value]等同于Dictionary<Key, Value>

上下文有类型,根据字面量:dict = [:]

字面量:var dict: [String: String] = ["1" : "3", "k": "v"]

访问:

dict.count:键值对数量

dict.isEmpty:是否为空

遍历:

for(key, value) in dice {

}

for k in dict.keys {

}

for v in dict.values {

}

dict.values.sorted()

dict.keys.sorted()

修改:

dict[key] = val //字典下标返回的是一个可选值

dict.updateValue(_:forKey:):更新特定键的值,返回原值。找不到旧值会新增?

dict[key] = nil: 删除一个键值对

dict.removeValue(forKey:):移除键值对,返回被移除的值或nil

*元组

www.jianshu.com/p/464b7a36d…

泛型类型:

命名类型

枚举

范型

尖括号里写一个名字来创建一个泛型函数或者类型

范型函数,方法,类,枚举和结构体

类型名后面使用 where 来指定对类型的一系列需求,比如,限定类型实现某一个协议,限定两个类型是相同的,或者限定某个类必须有一个特定的父类。

<T: Equatable><T> ... where T: Equatable> 的写法是等价的。

func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {

    var result = [Item]()

    for _ in 0..<numberOfTimes {

        result.append(item)

    }

    return result

}

makeArray(repeating: "knock", numberOfTimes: 4)



// 

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool

    where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {

        for lhsItem in lhs {

            for rhsItem in rhs {

                if lhsItem == rhsItem {

                    return true

                }

            }

        }

        return false

}

anyCommonElements([1, 2, 3], [3])

类型安全和类型推断

编译时会进行类型检查。不匹配的类型为错误。

非显示指定类型(:Float),会用类型推断选择合适的类型

类型推断:根据赋值时的字面量推断。整型用int,浮点型用double。同时有整型和浮点型,是double

类型转换

值永远不会被隐式转换为其他类型。如果你需要把一个值转换成其他类型,请显式转换

SomeType(ofInitialValue) 是调用 Swift 构造器并传入一个初始值的默认方法。在语言内部,

UInt16 有一个构造器,可以接受一个 UInt8 类型的值,所以这个构造器可以用现有的 UInt8来创建一个新的 UInt16。注意,你并不能传入任意类型的值,只能传入 UInt16 内部有对应构造器的值。不过你可以扩展现有的类型来让它可以接收其他类型的值(包括自定义类型)

强制类型转换

uint16(uint8)

double(int)

int(double):截断

int(float):截断

int(string)

类型别名

typealias type_1 = UInt16



var name_2 = type_1.min 

var name_3: type_1 = 12