Swift基础总结

...闭区间
..>开区间

1、

/// 遍历
for i in 1…10 where i % 2 == 0{ //where限制条件
    print(i)
}

for i in (1...10).reversed(){// .reversed方向遍历
    
}

2、

//外部参数, 内部参数
func song(_ total:Int){
    for i in(1...total).reversed(){// total属于内部参数
        print("现在有\(i)部iPhone,卖出了一部,还剩\(i-1)部啦")
    }
    print("全部卖光了")
}
song(10) // _属于外部参数,外部参数留空

3、 面向对象编程,简称OOP

//初始化话--实例化,从class-->object的过程
class People{ //类是全局的,不需要其他类导入,直接可以使用
    let name: String
    let gender: String
    init(detailName:String,detailGender:String) {
        name = detailName
        gender = detailGender
    }
}
let zhangSan = People(detailName: "张三", detailGender: "男")

4、 数组中放对象的情况非常多

// 数组的两个常用功能: 按元素大小排序 转换
let avs2 = arrays.sorted()//排序
for av in avs2 {
  print(av)
}

let avengers = ["a","b","c"]
// $0代表其中一个元素
let avs3 = avengers.map {//转换
    return "字母:" + $0
}
print(avs3)

5、 泛型

// T为泛型类型(广泛使用的类型),是说明 T是可比较的类型
func bigger(a: T, b: T) -> T {
    if a > b {
        return a
    } else {
        return b
    }
}
var i = bigger(a: 3, b: 4)
var j = bigger(a: "a", b: "b")
print(j)
print(i)

6、 自定义类型

// struct 结构体 约等于 class-----不需要init,是一种轻量级的class
// struct 自定义类型 — (变量、函数的内部聚合)
struct Human {
    var name = ""
    var age = 0
    var height = 0
    
    func shuoming() {
        print("\(name)的年龄是\(age),身高是\(height)")
    }
}
var tonyStrk = Human(name: "Iron Man", age: 50, height: 180)
tonyStrk.shuoming()
print(tonyStrk.name)

//自定义类型 -- 外部组合 -- Swift特色
protocol flyable { // protocol协议
    func takeOff(speed: Int)
}
extension Human: flyable{//扩展 Human功能
    func takeOff(speed: Int) {
        print("\(name)将以时速\(speed)公里起飞")
    }
}
tonyStrk.takeOff(speed: 300)

7、 初始化

enum Type{
    case sports
    case sedan
    case SUV
}
class Car {
    var color = "black"
    var seats = 5
//    var type = Type.sports
    var type:Type = .sports
    /// 初始化构造器---这个class被实例化时执行的代码
    init(color:String,seats:Int,type: Type) {
        self.color = color
        self.seats = seats
        self.type = type
    }
    /// 遍历构造器
    convenience init(){
        self.init(color:"blue",seats:6, type:.sports)
    }
}

8、 可选类型Optional-那些看不懂的感叹号和问号

/// optional--可选型
var desk:String?

override func viewDidLoad() {
    super.viewDidLoad()

    //强制解包--wrap
    if(desk != nil){
        print("最近的" + desk!)
    }

    //可选绑定---简称iflet
    if let desk = desk {//有值的话,执行大括号里的内容
        print("最近的\(desk)")
    } 
}

9、 获取用户当前位置

import UIKit
import CoreLocation

// delegate--委托
// protocol--协议
class ViewController: UIViewController,CLLocationManagerDelegate {
    
    let locationManager = CLLocationManager()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager.delegate = self // CLLocationManager的代理人是self
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        locationManager.requestWhenInUseAuthorization()//请求授权获取当前位置
        locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters //设置位置精度, 精度越高, 耗电越大
        
        locationManager.requestLocation()//请求用户位置---只请求一次
    }
    
    //当请求用户位置的时候立刻调用这个方法(重要方法)
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let lat = locations[0].coordinate.latitude //经度
        let lon = locations[0].coordinate.longitude //纬度
        print(lat,lon)
    }
    //当位置请求失败时的回调(必须写)
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
    }
}

10、 计算属性

import Foundation

class Weather {
    var temp = 0
    var city = ""
    var condition = 0
    
    //计算属性--compute属性
    var icon:String{//需要根据别的属性来确定自己是什么的时候
        switch (condition) {
        case 0...300:
            return "tstorm1"
        default:
            return "未知"
        }
    }   
}

11、 类型转换

// 导航之前做的一些准备操作----大多数情况是传值
override func prepare(for segue:UIStoryboardSegue,  sender:Any?){
    if segue.identifier == "selectCity" {
        // as--->向上转型upcasting或转换一般类型(类似于Int(3.2)) ---用的少
        // as?--->向下转型---downcasting(可能为空的情况下使用,要用iflet.)
        // as!--->向下转型---downcasting(强制转换类型,在明确的情况下使用)
        let vc = segue.destination as! selectViewController
      vc.currentCiyt = weather.city
    }
}

12、 找到tableView所点击的cell

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
       
    //找到点击的那个cell
    let cell = tableView.cellForRow(at: indexPath) as! TodoCell
    //取消cell的选择状态(也就是把底色去掉)
    tableView.deselectRow(at: indexPath, animated: true)
}

13、 iflet多条件判断

//判断用户有没有输入(为nil的情况) + 用户是否只输出了空格(空字符串的情况)
if let name = todoInput.text, !name.isEmpty{
    
}

14、 更新tableview视图

// 更新视图---view
    tableView.beginUpdates()
    tableView.deleteRows(at: indexPath, with: .automatic)
    tableView.endUpdates()//把批量对视图的操作放在这两句话中间就能提高APP的性能
        
//  tableView.reloadData()//在更新完数据(model)之后,这一句话就可以代替更新视图的那些代码,但是没有动画

15、 tableview cell编辑状态

/// 当用户点击editButton(编辑cell)之后会调用这个方法
override func setEditing(_ editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)
    editButtonItem.title = isEditing ? "完成" : "编辑"
}


 /// 右滑删除
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        //删除数据
        todos.remove(at:indexPath.row)
        //2.更新tableview视图view
        tableView.deleteRows(at: [indexPath], with: .fade)
    } else if editingStyle == .insert {

    }    
}

/// 更改右滑按钮title
override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
    return "删除"
}

// 移动cell
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
    //1.移动数据
    let todo = todos(fromIndexPath.row)
    todos.remove(at: fromIndexPath.row)
    todos.insert(todo, at: to.row)
    //2.更新视图
    tableView.reloadData()
}

16、 定义空数组字典

//定义空数组
    var todos:[Todo] = []//也可以写成 var todos = [Todo]() 或者 var todos: Array = []
    //定义空字典
    var dic:[String:String] = [:]//也可以写成 var dic = [String:String]

17、对象编码, userdefaluts存储对象, data解码

import Foundation
//sp1.让todo遵守codable协议, 使之可以编码
struct Todo:Codable {
    var name = ""
    var checked = false 
}

//sp2.把数据存到本地(iPhone手机)
func saveData() {
    //编码的固定格式----先创建一个编码器(JSONEncoder())----然后编码(encode)
    do{
        //编码后得到的data类型的数据------说白了就是一堆字符串
        let data = try JSONEncoder().encode(todos)
        UserDefaults.standard.set(data, forKey: "todos")
    }catch{
        print(error)
    }
}

//sp3.从沙盒读取数据
func readData()  {
    //沙盒的位置--sandbox
    print(FileManager.default.urls(for: .documentDirectory, in: .userDomainMask))
    if let data = UserDefaults.standard.data(forKey: "todos") {
        //解码的固定格式---先创建一个解码器( JSONdecode() )---然后解码(decode)
        do{
            //解码为[Todo]类型---固定写法(.self)
            todos = try JSONDecoder().decode([Todo].self, from: data)
        }catch{
            print(error)
        }
    }
}

18、存储

/*
 软件产品的两种形态:cs和bs
    client-server----QQ,微信--所有我们安装的软件--本地存储的多
    //比如微信会把聊天记录里面的数据全部存储在本机上
    //本地存储的增删改查很快, 所以我们的APP比起网站运行速度要快
 
    browser-server-----网站, 在线聊天---服务器存储用的多
    //服务器需要和数据库连接, 这个连接非常耗时, 导致我们网站响应速度并没有软件cs快
 
 本地存储数据库:
 //1. userdefaults--存储轻量级的数据
 //2. core data--苹果自带的-学习成本高, 代码多, 速度e没有realm快--不推荐用
 //3. realm--第三方功能包
 
 数据库:
    userdefaults本质上是存储plist文件
    core data和realm 本质上是一些按项目需求写好的每列是什么的表格(exal),并存储在一个文件里, 便于我们进行数据的增删改查
 */

19、使用Realm

let realm = try! Realm()
var todos: Results?//realm里面的类型---结果集的意思---类似数组的一种混合数据类型

//用Realm把数据存储到本地(iPhone手机)
func saveData(todo:Todo) {

    //打印存储地址
    print(Realm.Configuration.defaultConfiguration.fileURL)

    do {
        let realm = try Realm()
        try realm.write {
            realm.add(todo)
        }
    } catch {
        print(error)
    }
}

//从Realm里面读取全部数据
func readData(){

    todos = realm.objects(Todo.self)//Todo.self表示传入Todo类型
}

//从Realm里面改写数据
func writeData(){
    do {
        try realm.write {
            todos![indexPath.row].name = name
        }
    } catch{
        print(error)
    }
}

//从Realm里面删除数据
func delData(){
    do {
        try realm.write {
            realm.delete(todos![indexPath.row])
        }
    } catch{
        print(error)
    }
}

//Realm搜索排序
func searchData() {

    //1. predicate--断言--规定要怎么查询部分数据
    //ascending不写的话默认是true(升序)
    todos = realm.objects(Todo.self)?.filter("name CONTAINS %@",searchBar.text!).sorted(byKeyPath:"createdAT",ascending:false)
}

20、让view立刻重新布局

self.view.layer.layoutIfNeeded()

21、取消自动约束

//用代码写的控件,默认情况下xcode会帮我们推断出约束, 我们要自定义约束所以定为false
imageView.translatesAutoresizingMaskIntoConstraints = false

//设定初始的约束值---宽,高,x,y
let conWidth = imageView.widthAnchor.constraint(equalToConstant: 100)
let conHeight = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor)
let conX = imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
let conY = imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 100)
NSLayoutConstraint.activate([conWidth,conHeight,conX,conY])//激活这些约束
view.layoutIfNeeded()//立刻生效(防止掺和到animate里去)

22、参数名缩写功能

// swift自动为闭包提供参数名缩写功能,可以直接通过$0和$1等来表示闭包中的第一个第二个参数,并且对应的参数类型会根据函数类型来进行判断:

//不使用:
let numbers = [1,2,5,4,3,6,8,7]
        sortNumbers = numbers.sorted(by: { (a, b) -> Bool in
            return a < b
        })
        print("numbers -" + "\(sortNumbers)")

//使用 $0,$1
let numbers = [1,2,5,4,3,6,8,7]
 var sortNumbers = numbers.sorted(by: {$0 < $1})
 print("numbers -" + "\(sortNumbers)")

23、@escaping @ noescaping 逃逸闭包与非逃逸闭包

  Swift 3.0之后,传递闭包到函数中的时候,系统会默认为非逃逸闭包类型(NonescapingClosures)@noescaping,逃逸闭包在闭包前要添加@escaping关键字。

从生命周期看两者区别:

非逃逸闭包的生命周期与函数相同:

1,把闭包作为参数传给函数;

2,函数中调用闭包;

3,退出函数。结束



逃逸闭包的生命周期:

1,闭包作为参数传递给函数;

2,退出函数;

3,闭包被调用,闭包生命周期结束

你可能感兴趣的:(Swift基础总结)