第一节_基本知识
Mac和Xcode一些快捷键
command键:win键,option键:alt键
复制:com+c,粘贴:com+v,剪切:com+x
保存:com+s,撤销:com+z
运行程序:com+r
注释、取消注释:com+/
单步运行:F6数据类型
- 数值类型:int,uint(无符号整数),float,double
- 字符串类型:String
- 布尔类型(Bool):true/false
- 枚举类型
注:Swift中不强制要求定义类型,强制定义的只有常量let、变量var
let值初始化后即不能再更改
数值类型
1
2
3
4int,uint(无符号整数),float,double四种基本数值类型
let n = 70 //结尾无需分号
let m = 50.0 //等号两边空格数必须相等
var n:Double = 50 //显示定义类型字符串类型
1
2
3
4
5
6
7
8
9
10
11格式化字符串
var n = 50
var m = 60
var str1 = "I have \(n + m) pencils" // \(表达式)为格式化字符串
var str2 = "I have " + (String)(n + m) + " pencils" //效果相同
字符串的下标是String.index类型,不是int类型,不能直接用int作下标
startIndex:指向首字符;endIndex:指向末字符的后面;offsetby:偏移量。
let index1 = str.index(str.startIndex, offsetBy:1) //指向首字符后一字符
let index2 = str.index(str.endIndex, offsetBy:-1) //指向末字符
str2 = str[index1..<index2] //截取字符串,前闭后开区间
计算字符串长度:str2.count
比较字符串是否相等:== 和 !=
在Swift中字符串是值类型,复制传递的是字符串的值而非引用
枚举类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17enum DaysOfWeek{ //定义枚举类型
case Sunday
case Monday
case Tuesday
dase Wednesday
case Thursday
}
var day = DaysOfWeek.Sunday //用句号引出枚举项
day = .Monday //已确定day是DaysOfWeek类型,即不用再写,但句号必须写
enum ea : String{ //若枚举项有rawvalue,则必须写类型值
case a1 = "aa1"
case a2 = "aa2"
case a3 = "aa3"
}
let result = ea(rawValue:"aa1") //由raw值查枚举项,返回Option(ea.a1)
print(result!) //拆包,输出a1合集类型(Collection)
- 数组和区间
- 字典(dict):键值对
- 集合(set):无序、不重复数组
三种类型都可用xx.count表示元素数量1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//数组
var an1 = [1,2,3,4]
var an2 : [Int]
an2 = [1,2,3,4]
//区间
an1[1..<3] //an[1],an[2]
an1[1...3] //an[1],an[2],an[3]
//字典
var dic: [String : Int]
dic = ["Red":0,"Green":1,"Bule":2]
dic["Red"] //0
//集合
let s1 = Set([1,2,3])
let s2 : Set<Int>
s2 = [1,2,3]
- 可选值Optional
类型后加?为可选值,代表声明的变量可能为空(nil)1
2
3
4
5
6
7
8
9
10let dic = [0:"Red",1:"Blue",2:"Yellow"]
var color = dic[0] //color为String?类型,可能会返回nil值
print(color) //输出Optional("Red"),对"Red"封包了
if color! = nil{ //color不为空才执行操作
let actualColor = color! //对Optional("Red")拆包
}
else{
//统一在拆包阶段对nil进行处理,逻辑更清晰
}
第二节_语句
for-in循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19for index in 1...5{
print(i)
} //条件不用加括号,但语句体要加中括号
//遍历数组
var an = [1,4,7,22,5]
for index in an{
print(index)
}
//遍历字典
let d = [0:"Red",1:"Green",2:"Blue"]
for key in d.keys{
print("\(key)->\(d[key])") //输出的是可选值
}
for(key,value) in d{
print("\(key)->\(value)") //输出正常值
}switch-case
1
2
3
4
5
6
7
8
9
10
11
12
13//没有break
//一个case可对应多个选择值
//最后必须加default
let x:Character = "1"
switch x {
case "a","b","d":
print("1")
case "s","e","p":
print("2")
default:
print("3")
}函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16函数定义
func hello(name:String)->String{
return "Hello, " + name
}
调用
str="lrrr"
hello(name:str) //函数调用不能省略参数名称
//多返回值函数,用元组作返回值
func hello(n:Int)->(n1:Int,n2:Int){
let n1 = n+1
let n2 = n+2
return (n1,n2)
}
let total = hello(n:1)
print(total) //输出“(n1: 2, n2: 3)”
第三节_IOS开发
MVC模式
Model-View-Controller(模型-视图-控制器),面向对象的常用模式
模型:保存数据的类
视图:UI控件
控制器:把模型和控制器绑定在一起的类,以及实现中间逻辑层。
优点:可最大限度地分离这三类代码(数据、UI、逻辑),每个类只实现专一的功能。控制类的绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17输出接口:
@IBoutlet weak war myButton: UIButton! //可与控件绑定的变量(Button按钮)
操作方法:
IBAction func doSomething(sender: UIButton){
//可响应控件所触发事件的函数,sender为控件类型
}
绑定:
在View视图上,(ctrl+左键)/右键拖住控件,拖向辅助编辑器中的viewControl.swift文件,
新建一个接口/方法,或绑定已有代码。
注:和已有代码绑定时,只有类型匹配才会出现绑定框。
一般流程:
控件A绑定Action,在绑定Action时指明响应什么Event,控件B绑定outlet,
在Action中对outlet进行操作,相当于对控件B操作。
Event触发时,执行Action,操作outlet,界面UI发生改变。网络传输(HTTP协议)
HTTP协议分为请求头和数据部分,请求头系统有内置属性,后台也是tomact服务器会自动处理
数据部分则是和后台自己约定的,比如提交到哪个文件夹,提交的文件叫什么名字等等。
1 | //先把HTTP数据部分写好(Data形式),方便后面传入request中 |
多线程操作
在GUI中,默认操作都是在主线程中完成的(对控件的操作,以及与控件无关的操作),因此如果有非常耗时的操作,就需要另开一个线程,放在其中执行,否则耗时的操作会使主线程阻塞,导致UI界面无法操作(点击按钮、输入文本等)。
而在分线程中,如果涉及到对UI界面的操作,就要再手动回到主线程中去操作相应控件,在swift中对应为DispatchQueue.main.async {//code}
。
swift中的线程操作,可通过GCD(Grand Central Dispatch)的方式完成,其将代码以队列(先进先出)的形式放入其他线程中执行。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//...code1
let queue = DispatchQueue.global(qos:.default)
queue.async {
//code3
DispatchQueue.main.async {
//在分线程中回到主线成中操作UI
upImgButton.isEnabled = false
}
}
//...code2
//代码说明:
//code1执行完后,建立线程队列queue,系统将块内的代码放入队列中,但并不会立即执行
//之后会执行code2,等当前线程时间片到了,才会去执行queue线程中的代码
//若没有并行设置,queue线程中的代码默认是顺序执行的IOS图像格式
关于IOS的图像系统,有三种格式- UIImage:在UIKit框架下显示的图像格式,用于UI显示,通过UIImageView.image调用或赋值
- CIImage:CoreImage框架操作的图像格式,CI框架的函数都是针对这个数据格式
- CGImage:位图格式,底层的图像存储格式,UI和CI本质都是对CGImage的封装
1
2
3
4
5
6
7
8
9//三种图像的互相转换,UI和CI图像的转换都是通过CG间接完成的
UI->CG:UIImage.cgImage
UI->CI:CIImage(cgImage: UIImage.cgImage)
CG->UI:UIImage.init(cgImage: CGImage)
CG->CI:CIImage(cgImage: CGImage)
CI->UI:UIImage.init(cgImage: CIImage.cgImage)
CI->CG:CIImage.cgImage
人脸识别(系统库)
参考博文:https://www.jianshu.com/p/e371099f12bd1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119//IOS内置的图像处理库,用于处理一些复杂的图像操作
import CoreImage
//人脸识别函数的传入参数之一
let imageOptions = NSDictionary(object: NSNumber(value: 5) as NSNumber, forKey: CIDetectorImageOrientation as NSString)
//未识别的原始照片
let personciImage = CIImage(cgImage: imageView.image!.cgImage!)
//定义精确度,High为较高的精度
let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
//定义人脸识别器
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
//识别人脸,返回人脸数组
let faces = faceDetector?.features(in: personciImage, options: imageOptions as? [String : AnyObject])
//因为UI和CI两大框架的坐标系原点不相同
//UI为左上角,CI为左下角,因此要进行坐标变化
//否则人脸的位置坐标不对
let ciImageSize = personciImage.extent.size
//改变x,y延伸方向
var transform = CGAffineTransform(scaleX: 1, y: -1)
//改变原点位置
transform = transform.translatedBy(x: 0, y: -ciImageSize.height)
if let face = faces?.first as? CIFaceFeature {
//进行坐标系变换
//face.bounds返回识别的人脸CRect框,包括起点位置和图像宽、高
let faceImgBounds = face.bounds.applying(transform)
let sourceImageRef: CGImage = imageView.image!.cgImage!
//根据Rect截取人脸
let newCGImage = sourceImageRef.cropping(to: faceImgBounds)
var tempImage = UIImage.init(cgImage: newCGImage!)
//对截取的人脸图像进行压缩
let tempCGSize = CGSize(width:tempImage.size.width/4,height:tempImage.size.height/4)
UIGraphicsBeginImageContext(tempCGSize)
tempImage.draw(in: CGRect(x: 0, y: 0, width: tempCGSize.width, height: tempCGSize.height))
//因为图像会有向左旋转90度的bug,因此要进行修正
tempImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
tempImage = tempImage.fixOrientation()
//写入ImageView中
faceImg.image = tempImage
}
else {
let alert = UIAlertController(title: "提示", message: "未检测到人脸", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "确定", style: UIAlertActionStyle.default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// 修复图片旋转代码,扩展UIImage类
//根据图像的imageOrientation属性值来进行旋转
extension UIImage {
func fixOrientation() -> UIImage {
// if self.imageOrientation == .up {
// return self
// }
var transform = CGAffineTransform.identity
switch self.imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: self.size.width, y: self.size.height)
transform = transform.rotated(by: .pi)
break
case .left, .leftMirrored:
transform = transform.translatedBy(x: self.size.width, y: 0)
transform = transform.rotated(by: .pi / 2)
break
case .right, .rightMirrored,.up:
transform = transform.translatedBy(x: 0, y: self.size.height)
transform = transform.rotated(by: -.pi / 2)
break
default:
break
}
switch self.imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: self.size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
break
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: self.size.height, y: 0);
transform = transform.scaledBy(x: -1, y: 1)
break
default:
break
}
let ctx = CGContext(data: nil, width: Int(self.size.width), height: Int(self.size.height), bitsPerComponent: self.cgImage!.bitsPerComponent, bytesPerRow: 0, space: self.cgImage!.colorSpace!, bitmapInfo: self.cgImage!.bitmapInfo.rawValue)
ctx?.concatenate(transform)
switch self.imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx?.draw(self.cgImage!, in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.height), height: CGFloat(size.width)))
break
default:
ctx?.draw(self.cgImage!, in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(size.width), height: CGFloat(size.height)))
break
}
let cgimg: CGImage = (ctx?.makeImage())!
let img = UIImage(cgImage: cgimg)
return img
}
}
Post Date: 2018-01-27
版权声明: 本文为原创文章,转载请注明出处