第一节_基本知识

  • Mac和Xcode一些快捷键
    command键:win键,option键:alt键
    复制:com+c,粘贴:com+v,剪切:com+x
    保存:com+s,撤销:com+z
    运行程序:com+r
    注释、取消注释:com+/
    单步运行:F6

  • 数据类型

  1. 数值类型:int,uint(无符号整数),float,double
  2. 字符串类型:String
  3. 布尔类型(Bool):true/false
  4. 枚举类型
    注:Swift中不强制要求定义类型,强制定义的只有常量let、变量var
    let值初始化后即不能再更改
  • 数值类型

    1
    2
    3
    4
    int,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
    17
    enum 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)

  1. 数组和区间
  2. 字典(dict):键值对
  3. 集合(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
    10
    let 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
    19
    for 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
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
//先把HTTP数据部分写好(Data形式),方便后面传入request中
//name是要提交到哪个文件夹,filename为文件上传后的文件名
//7d4a661c433为分隔符,任意string串都可以。以'--'+分隔符开头,固定格式。
//'\r\n'表示换行,属性间是否换行也是固定格式。

//数据部分的开头,最后的要转成utf8格式
var postdata:Data = "--7d4a661c433\r\nContent-Disposition: form-data;name=\"uploadFile\";filename=\"lizec.jpg\"\r\nContent-Type:application/octet-stream\r\n\r\n".data(using: String.Encoding.utf8)!

//具体的数据部分,直接写入即可
postdata.append(UIImagePNGRepresentation(faceImg.image!)!)

//数据部分结尾
postdata.append("\r\n\r\n--7d4a661c433--\r\n".data(using: String.Encoding.utf8)!)

//定义请求函数,写成函数形式便于之后写回调函数
//postData为HTTP数据部分,webServerUrl为服务器的地址
func requestfun(_ postData:Data,webServerUrl:String){
let session:URLSession = URLSession.shared
let url:URL = URL(string:webServerUrl)! //将String形式的服务器地址转为URL形式

//定义HTTP请求头及相关属性,这部分是HTTP固定的属性
//用url初始化request,NSMutableURLRequest形式
let request:NSMutableURLRequest = NSMutableURLRequest(url:url)
request.timeoutInterval = 30
request.httpMethod = "POST"
request.httpBody = postData
request.setValue("UTF-8", forHTTPHeaderField: "Charsert")
//设置boundary,即分隔符
request.setValue("multipart/form-data;boundary=7d4a661c433", forHTTPHeaderField: "Content-Type")

//定义回调任务
//传入的request参数为NSMutableURLRequest形式的HTTP请求
//data为后端发来的数据(系统已自动将数据部分拆出来了)
let task = session.dataTask(with: request as URLRequest){ (data: Data?, response: URLResponse?, error: Error?) -> Void in
//有回调数据
if data != nil {
tempText = String(data:data!, encoding: String.Encoding.utf8)!
//print(tempText!)
sign = 1 //回调函数执行完

} else {
print("发送请求出错:\(String(describing: error?.localizedDescription))")
sign = 1
}
}

//执行回调任务
//系统定时查询后端有无response发过来,检测到response后即执行回调任务
//因此其他地方要等待回调函数执行才能更新,可while()循环检测标志位
task.resume()
}
}

//最后调用请求函数即可
requestfun(postdata, webServerUrl:"http://123.207.30.222:8080/WebHello/UploadServlet")
  • 多线程操作
    在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/e371099f12bd

    1
    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

版权声明: 本文为原创文章,转载请注明出处