【Swiftの基本構文とSnapKit自動レイアウトライブラリの使い方】

序文

最近、Swiftを勉強してプロジェクトを書いています。シンプルで安全な言語だと感じています。基本的な構文と必要な知識を学んだ後、OCのUIも自動レイアウトを使用しているため、Swiftの自動レイアウトについても調べました。ライブラリ SnapKit 、簡単に記録します。

遊び場

文法を練習するためにプレイグラウンドを開くと便利ですが、
画像の説明を追加してください
場合によってはまとめて覚えられないこともあります。

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)

文字列辞書配列

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
}

  • Swift の辞書と OC の間のギャップはまだ比較的大きいです. Swift の型はどれも、それを宣言するときにその型を明確にしなければなりません.swiftの研究を通じて、読者はコレクション型の場合、その内部要素の型が宣言時に明確にされなければならないことを知る必要があります。辞書も例外ではありませんArraySet
  • 今日、Zhihu Daily のインターフェイスをテストしたところ、OC と同様に複数のレベルの要素に直接アクセスできず、エラーが報告されることがわかりました。
  • ディクショナリ内のネストされた配列を反復処理するには、次の操作が必要ですが、マルチレベルの 1 回限りのアクセスを実現するのは依然として困難です。その後、Swift の JSONModel ライブラリを学習する必要があります。これもサードパーティのライブラリであり、 OCとあまり変わりません。
if let stories = dict["stories"] as? [[String: Any]] {
    
    
    for story in stories {
    
    
        if let title = story["title"] as? String {
    
    
            print("Title: \(title)")
        }
        
        if let content = story["content"] as? String {
    
    
            print("Content: \(content)")
        }
        
        if let tags = story["tags"] as? [String] {
    
    
            for tag in tags {
    
    
                print("Tag: \(tag)")
            }
        }
        
        // 其他键值对的访问...
    }
}

閉鎖

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


列挙型

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との違いをより簡潔に

まず、この言語には最初からインターフェイス ファイルが存在せず、インターフェイスと実装が 1 つのファイルに含まれており、特定のサードパーティ ライブラリがない限り、ヘッダー ファイルを作成せずに一部のインターフェイスで特定の 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で作業する際、もともとマクロを使って画面サイズなどを定義していたのですが、グローバルファイルを発見しました。

画像の説明を追加してください
グローバル ファイルで定義されたコンテンツは、複数のファイルで使用でき、いつでもアクセスできます。画像の説明を追加してください

  • たとえば、グローバル ファイル内のいくつかのプロジェクトで使用される背景色、長さ、幅を定義しました。
  • 今日、値を渡す通知を書いていたら、ここで名前を定義できることがわかり、とても便利でした。

スナップキットの使い方

以前のサードパーティ ライブラリの使用と同様に、ポッドをダウンロードした後に使用できます。
画像の説明を追加してください
石積みと何ら変わらない感じです。

topそしてtopMargin

SnapKit では、topと はtopMarginビューの上マージンを設定するために使用される 2 つの異なる制約プロパティです。

  1. top属性:

    • topプロパティは、スーパービューまたは参照ビューの上マージンに対するビューの上マージンの距離を表します。
    • これは、スーパービューまたは参照ビューの真の上マージンを基準にして計算されます。
    • 制約を設定する場合、多くの場合、ビューの上マージンとその親ビューまたは参照ビューの間の距離を特定の値に設定する必要があります。
  2. topMargin属性:

    • topMarginプロパティは、スーパービューのレイアウト マージンに対するビューの上マージンの距離を表します。
    • これは、スーパービューのレイアウト余白に対して制限されます。
    • top属性と比較して、topMargin属性ではレイアウトの余白の影響が考慮されるため、ビューの位置がより適応的かつ柔軟になります。
    • 一部のレイアウト、特に AutoLayout とマージン レイアウトを使用する場合、topMarginこのプロパティを使用するとマージンの変更と調整をより適切に処理できます。

一般に、topプロパティはビューの実際の上マージンに基づいて制約されますが、topMarginプロパティは親ビューのレイアウト マージンに基づいて制約されます。レイアウトのニーズと使用シナリオに基づいて、適切なプロパティを選択して、ビューの上マージンの制約を設定します。

大きな違いはないと思いますが、topは問題なく使用しています。

要約する

Swift の辞書、配列、タプルはプロジェクトを書くときにあまり使われません。辞書に関しては、エラーを報告せずに複数のレイヤーで読み取る方法など、かなり問題が多いようです。OC との違いはまだあります。まとめます。それらを勉強してから。

おすすめ

転載: blog.csdn.net/weixin_61639290/article/details/131096370