文章目录
- 前言
- playground
- var 和 let-元组
- string-字典-数组
- 闭包
- enum
- 类和对象
- 属性
- 类
- UI
- 和OC的区别,更简洁
- 懒加载
- 全局文件
- snap kit的使用
- `top` 和 `topMargin`
- 总结
前言
最近在学习swift和写项目,给我的感受,语言简洁和安全,在学习了基础的语法和一些必要的知识之后,因为OC的UI也用到了自动布局,所以也去探索了swift的自动布局库SnapKit,简单记录一下。
playground
开playground练习语法比较方便
有时候有些东西编译不出来记得
var 和 let-元组
import UIKit
var greeting = "Hello, playground"
var str = "hello"
str += "11"
print(str)
var a:Int = 1, b: String = "2", c:Double = 3.0
print(a, b, c)
print("b.count =", b.count, "sss")
var smile = "smile\n"
print(smile)
// 不能数字命名开头
//var 1x = 12;
//print(1x)
// 元组
var person:(name:String, age:Int) = ("iOS", 19)
print(person.name)
var car:(String, Int) = ("Benz", 10000)
var (theName, thePrice) = car
print(theName, thePrice)
// 匿名
// 在Swift语言中,常常使用符号“_”来表示匿名的概念,因此“_”也被称为匿名标识符。
var (theName1, _) = car
var obj: String? // 在普通类型后面添加符号“?”,即可将普通类型包装为Optional类型。
// 在Swift语言中,未做初始化的普通类型是不允许使用的
if obj == nil {
print("!obj")
}
// 在使用“!”进行Optional值的拆包操作时,必须保证要#包的值不为nil,否则程序运行会出错。可以在拆包前使用if语句进行安全判断
//声明obj为String?类型
var obj2: String? = "safe"
if obj != nil {
obj!
}
// if-let结构中也可以同时进行多个Optional类型值的绑定
// 只有所有Optional值都不为nil,绑定才会成功,代码执行才会进入if为真的代码块中
var curObj: Int? = 9
if let temp = curObj {
print(temp)
} else {
curObj = 10;
}
// 当我们明确某个变量初始时为nil,并且在之后使用之前一定会被赋值时,我们可以将其声明为隐式解析的可选值,再对这个变量进行使用,就不需要进行拆包操作了
// 声明obj4为隐式解析的变量
var obj4:Int!
obj4 = 3
// 在使用时,无须再进行拆包操作,Swift会自动帮我们拆包
print(obj4 + 1)
string-字典-数组
import UIKit
var greeting = "Hello, playground"
var str = String(describing: Int.self)
var a = Int(1.9)
var my = "jackDao"
// 符串插值方法
// \()”结构可以将其他数据类型转换为字符串类型并且插入字符串数据的相应位置,也可以进行简单的运算逻辑后将结果插入原字符串中
var myself = "my name is \(my)"
print(myself)
MemoryLayout<String>.size //16个字节 获取String类型占用的内存空间
var e:Character = "a"
var e2: [Character] = ["H", "E", "L", "L", "O"]
var e3 = String(e2)
// 使用for-in遍历可以将字符串中的字符拆解出来,这种方法有时十分好用,for-in遍历是Swift语言中一种重要的代码流程结构。String类型默认实现了迭代器相关协议,直接对其进行遍历可以取出字符串中的每一个字符元素
for charceter in e2 {
print(charceter)
}
//判断字符串是否为空
var obj1 = ""
if obj1.isEmpty {
print("字符串为空字符串")
}
// 在比较两个字符串的大小时,会逐个对字符的大小进行比较,直至遇到不相等的字符为止
var cp1 = "comp1", cp2 = "comp2"
if cp1 < cp2 {
print("cp1 is Small")
}
var string2 = "My name is Jaki"
//全部转换为大写
string2 = string2.uppercased() //结果为"MY NAME IS JAKI"
//全部转换为小写
string2 = string2.lowercased() //结果为"my name is jaki"
//检查字符串是否有My前缀
string2.hasPrefix("My")
//检查字符串是否有jaki后缀
string2.hasSuffix("jaki")
var array: Array<Int>
var array2: [Int]
array = []
array2 = Array()
array = [1, 2, 3]
array2 = Array(arrayLiteral: 1, 3, 4)
var array3 = [String](repeating: "Hello", count: 10);
var array4 = Array(repeating: 1, count: 10)
//声明字典[param1:param2],这种结构用于表示字典类型,param1为键类型,param2为值类型
var dic1:[Int:String]
//这种方式和[:]效果一样,dic2与dic1为相同的类型
var dic2:Dictionary<Int,String>
//字典创建与赋值
dic1 = [1: "1", 2: "2", 3: "3"]
dic2 = Dictionary(dictionaryLiteral: (1, "1"),(2, "2"),(3, "3"))
//在创建字典时,也可以不显式声明字典的类型,可以通过赋初值的方式来使编译器自动推断
var dic3 = ["1": "one"]
//创建空字典
var dic4: [Int:Int] = [:]
var dic5: Dictionary<Int,Int> = Dictionary()
1==2 //等于比较,返回false
1<2 //小于比较,返回true
1>2 //大于比较,返回false
1 != 2 //不等于比较,返回true
1<=2 //小于等于比较,返回true
1>=2 //大于等于比较,返回false
for index in 1...10 {
print(index)
}
var sum = 0
for _ in 1...10 {
sum += 1
}
闭包
import UIKit
var greeting = "Hello, playground"
// 一个完整的函数包含函数名、参数列表、返回值和函数体,示例如下:
//标准函数,这个函数的功能是计算某个整数的平方
func myFunc(param: Int) -> Int {
return param * param
}
// 将上面函数的功能使用闭包来实现,代码如下:
//闭包的实现方式
let myClosures = {(param1: Int) -> Int in
return param1 * param1
}
/*闭包在语法上有这样的标准结构:{(参数列表)->返回值in闭包体}。首先闭包的最外层由大括号包围,内部由闭包关键字in来进行分割,关键字in前面为闭包结构的参数列表和返回值,其书写规则与函数一致,关键字in后面为闭包体,用于实现具体功能*/
//对函数进行调用,将返回9
myFunc(param: 3)
//对闭包进行调用,将返回9
myClosures(3)
// 闭包的返回值是可以省略的
//闭包的实现方式
let myClosures2 = {(param:Int) in
return param * param
}
var x = myClosures2(2)
var x1 = myClosures(2)
// 自定义前缀运算符
prefix operator ++;
prefix func ++(param1: Int) -> Int {
return param1 + 1;
}
var num = 10
++num // num++ error
enum
import UIKit
var greeting = "Hello, playground"
enum Surname {
case 赵, 钱, 孙, 李
}
//var sur: Surname
var sur = Surname.孙
类和对象
import UIKit
var greeting = "Hello, playground"
struct Car {
var price: Int
var brand: String
var pertol: Int
mutating func addPertol() {
if pertol <= 0 {
pertol += 1
print("add Pertol")
}
}
//在默认情况下,结构体和枚举的实例方法是不允许修改实例属性的,除非将方法标记为mutating。使用mutating关键字修饰的方法可以在方法内部修改实例属性,并且在方法执行完毕后,这些修改将会保持在实例中。
mutating func drive() {
if pertol > 0 {
pertol -= 1
print("drive 10 kilometers")
}
}
}
var car = Car(price: 10000, brand: "Benz", pertol: 5)
print("this \(car.brand) price is \(car.price), have \(car.pertol) pertol")
for _ in 1...10 {
if car.pertol == 0 {
car.addPertol()
} else {
car.drive()
}
}
// 在默认情况下,结构体和枚举的实例方法是不允许修改实例属性的,除非将方法标记为mutating。使用mutating关键字修饰的方法可以在方法内部修改实例属性,并且在方法执行完毕后,这些修改将会保持在实例中。
// 对引用类型进行比较操作,应使用等同运算符“===”
// Array、String、Dictionary、Set这些数据类型都是采用结构体来实现的,这点和Objective-C有着很大的区别。因此,在Swift语言中,Array、String、Dictionary、Set在数据传递时总是会被复制
属性
import UIKit
// 监听
var greeting = "Hello, playground"
class Teacher {
var name: String {
willSet(new) {
print("将要设施的新名字:\(new)")
} didSet(old) {
print("旧名字\(old)")
}
}
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
var teacher = Teacher(name: "jackLi", age: 19)
teacher.name = "lyt"
// 对比类属性,Swift语言中的类方法也是通过static和class关键字来声明的,static关键字声明的类方法又被称为静态方法,其不能被子类覆写,而class关键字声明的类方法可以被类的子类覆写
类
import UIKit
var greeting = "Hello, playground"
// 对于有继承关系的类,类型检查有如下原则:子类实例进行父类类型的检查可以检查成功。父类实例进行子类类型的检查不可以检查成功。
var str = "Hello ios"
if str is String {
print("greeting is String")
}
// 其实如果数组中的元素是不同类型,并且这些类型没有一个共同的基类,那么开发者可以使用AnyObject来作为引用类型的通用类型
// AnyObject是通用的引用类型
class myClassOne {
}
class myClassTwo {
}
class myClassthree {
}
var c1 = myClassOne()
var c2 = myClassTwo()
var c3 = myClassthree()
var classArray: Array<AnyObject> = [c1, c2, c3]
for objclass in classArray {
print(objclass)
}
// 在Swift语言中还提供了一种更加通用的类型Any,它可以用来描述任意类型,包括值类型和引用类型
print("anyClass")
var anyClassArray: Array<Any> = [c1, c2, c3, (1, 1), "anyType"]
for objclass in anyClassArray {
print(objclass)
}
UI
和OC的区别,更简洁
首先语言在初始的时候没有了接口文件,接口和实现是在一个文件里面的,并且我在某些界面不需要写头文件也能引用某些ViewController,除非特定的第三方库。
懒加载
- 延续懒加载的思想
- 语法简单 直接+lazy关键字 需要var不能let
- 在最上面的init方法里面匿名调用方法即可
lazy var mainBackImageView: UIImageView = {
let image1: UIImage = UIImage(named: "MainBack.png")!
let imageView: UIImageView = UIImageView(image: image1)
self.addSubview(imageView)
imageView.snp .makeConstraints { make in
make.width.equalTo(SIZE_WIDTH + 17)
make.height.equalTo(SIZE_HEIGHT + 17)
make.left.equalTo(-7)
make.top.equalTo(-7)
}
return imageView
}()![请添加图片描述](https://img-blog.csdnimg.cn/4242f4e15b524bb6a5c593daf5de482f.png)
全局文件
在swift的时候,本来宏定义屏幕的尺寸等,接着就发现了全局文件。
全局文件定义的内容可以在多个文件使用,随时访问。
- 例如我在全局文件定义了一些项目里面要用到的背景颜色,长宽。
- 今天在写通知传值的时候发现可以在这里定义name,也挺方便。
snap kit的使用
和以前的使用第三方库一样,都是pod下来就能用。
和masonry感觉没有区别。
top
和 topMargin
在 SnapKit 中,top
和 topMargin
是两种不同的约束属性,用于设置视图的顶部边距。
-
top
属性:top
属性表示视图的顶部边距相对于其父视图或参考视图的顶部边距的距离。- 它是相对于父视图或参考视图的真实顶部边距进行约束计算的。
- 通常在设置约束时,需要将视图与其父视图或参考视图的顶部边距之间的距离设置为特定值。
-
topMargin
属性:topMargin
属性表示视图的顶部边距相对于其父视图的布局边距的距离。- 它是相对于父视图的布局边距进行约束计算的。
- 与
top
属性相比,topMargin
属性会考虑到布局边距的影响,使得视图的位置更具适应性和灵活性。 - 在一些布局中,特别是在使用自动布局和边距布局时,使用
topMargin
属性可以更好地处理边距的变化和调整。
总的来说,top
属性是基于视图的真实顶部边距进行约束计算的,而 topMargin
属性是基于父视图的布局边距进行约束计算的。根据你的布局需求和使用场景,选择合适的属性来设置视图的顶部边距约束。
我感觉区别不是很大,一直用的top没啥问题。
总结
swift的字典和数组,元组在写项目的时候感觉没有用到很多,字典那块的问题好像还挺多的,包括如何多层读取不报错,和OC还是有区别,研究了再来总结