【swift】初学 笔记



2022年05月29日    Author:Guofei

文章归类: 语言    文章编号: 18001

版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2022/05/29/swift.html


数据类型

  • 变量用 var 声明
  • 常量用 let 声明
// 声明一个常量
var str1:String
// 声明多条
var a=1,b=2,c=3

基本数据类型

Int
Double
Float

Boolean: true/false

Sting:"Hello"
字符:"C"

类型别名

typealias MyType = Int

var a: MyType = 100

字符串

var a="hello"
var b="world"

// 字符串替换
var c="\(a) haha \(b)"

// 字符串相加
var c = a + b

// 添加
c.append("1")

//字符串是否为空
a.isEmpty
//字符串长度
a.count
// 判断开头和结尾
a.hasPrefix("hell")
a.hasSuffix("llo")


//字符串比较
a==b
a!=b
a<b

//打印本体/utf-8/utf-16
for i in a{
    print(i)
}

for i in a.utf8{
    print(i)
}
for i in a.utf16{
    print(i)
}

字符串2:

// string转int
Int("123")

进制

// 用不同的进制赋值,其实结果都一样
var a=0b10001
var b=0o21
var c=0x11

// 浮点数也可以用n进制或者科学计数法
var d=1.21875e1
var e=0xC.3p0

optional 类型

var a=Int("123")
//a 是optinal 类型

if a != nil{
    print(a!) //加!表示强制解析
}else{
    print("not number")
}

元组

let people=(18,"Tom")
let (age,name)=people


//也可以自定义字段名
let people=(age:18,name:"Tom")
people.age
people.name

字典

新建

// 方法1
var someDict =  [KeyType: ValueType]()
var someDict = [Int: String]()

//方法2
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
//查
var someVar = someDict[key]

//改
var oldVal = someDict.updateValue("One 新的值", forKey: 1)

//删
var removedValue = someDict.removeValueForKey(2)


//for-in
for (key, value) in someDict {
}
// enumerate
for (idx, key_val) in someDict.enumerate() {
}

// 单独取key-val
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)

// 其它方法
someDict.count
someDict.isEmpty

数组

创建

var someArray = [SomeType]()

var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)

var someInts:[Int] = [10, 20, 30]
//增
var someInts=[Int]()

someInts.append(2)
someInts+=[3,4,5]




//查
someInts[0]

//改
someInts[0]=999
someInts[0...2]=[9,8,7] //批量改


//删
someInts.popLast()

其它

count
isEmpty

for in

运算符

// 算术运算符
+
-
*
/
%
a+=1
a-=1

比较运算符(跟Python一样)

逻辑运算符

&& 与
|| 或
! 非

位运算符

~&|^

程序结构

if

if exp{
  statement1
}else{
  statement2
}


if exp1{
  statement1
} else if exp2{
  statement2
} else if exp3{
  statement3
} else {
  statement4
}

循环

//for-in
var nums:[Int]=[10,20,30]

for num in nums{
    print("val = \(num)")
}

// while
var idx=1

while idx<5{
    print(idx)
    idx+=1
}

函数和类

func funcname(形参) -> returntype
{
   Statement1
   Statement2
   ……
   Statement N
   return parameters
}


//如何返回一个tuple

func myfunc(nums:[Int])->(part1:Int,part2:Int){
    return (nums[0],nums[1])
}

let res=myfunc(nums:[1,2,3])
print(res.part1,res.part2)

占位符 T 和泛型

// x 和 y,以及返回都是 T 类型,where T 类型是 Comparable

func max<T>(_ x:T, _ y:T) -> T where T:Comparable{
    return y >= x ? y : x
}

// 也可以这样写
//func max<T:Comparable>(_ x: T,_ y: T) -> T{
//    return y >= x ? y : x
//}
max(1,2)
max("abc","bbc")



// 这个 Comparable 是一种协议,你可以定义自己的:


协议

Game 项目

  • AppDelegate:用来侦听当前设备状态
  • GameScene:主游戏场景
  • GameViewController
  • GameScene.sks 场景编辑器

label

self.label = self.childNode(withName: "//helloLabel") as? SKLabelNode

self.label.text="text"

xcode

  • control+i 格式化代码
  • swiftUI
    • 快速调出样式修改面板 command+点击 -> inspector

swiftUI

要点

图片 Assets

  • 直接拖动进去
  • 可以 command+f 搜索和替换
  • 不同的国家显示不同的图片:右边attribute->location
  • 深色/浅色模式显示不同图片:右边attribute->appearance

包管理

  • 左边点击项目名,中间会出现标签卡
  • 3给标签卡里面,点击 package dependencies
  • command+, 可以管理GitHub账号

模拟

  • 顶部菜单->window->Devices and Simulators
  • 可以添加真机/使用模拟机器
  • 可以模拟机器状态:拉到底下,有 Device Condition。可以模拟网络、设备温度。

swift ui语法

  • 文档和教程: https://developer.apple.com/cn/xcode/swiftui/
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello, World!")
                .font(.title)
                .foregroundColor(.yellow)
            HStack {
                Text("hello, hello, hello")
                    .font(.subheadline)
                    .foregroundColor(.yellow)
                Spacer()
                Text("Author")
            }
        }.padding()

    }
}

VStack/HStack/ZStack:纵向排列/横向排列/Z轴排列

  • 可以定义左对齐、居中对齐等 Vstack(alignment: .leading, spacing: 8)
  • List(0 ..< 5) 用法类似,重复使用

一些元素

  • Text(“hello”)
  • Spacer()
  • Image:
    • Image(systemName: "photo")
    • Image("图片")
    • .resizable() 默认显示原图大小,加这个可以缩放到适配屏幕大小
    • .clipShape(Circle()) 轮廓变成圆的
    • .overlay(Circle().stroke(Color.red, lineWidth: 4)) 外接一个边框,方式是覆盖一个东西
    • .shadow(radius: 10) 影子

如何重复列出元素?

//简单的方式
List(0 ..< 5) { item in
    HStack{
        Image(systemName: "photo")
        VStack(alignment: .leading) {
            Text("长城")
            Text("北京1111111")
                .font(.subheadline)
                .foregroundColor(Color.secondary)
        }
    }
}


//用list


//为了在调用的时候区分,有两种实现:
//1.可以用遵守 Identifiable 协议来实现
//2. 也可以用id字段来实现,调用的时候就用 List(landmarks).identified(by:\.id)
struct Landmak:Identifiable{
    var id=UUID()
    var name:String
    var detail:String

    var imageName:String{return name}
    var thumbnailName:String{return "\(name)的缩略图"}
}

let landmarks=[
    Landmak(name: "冰湖", detail: "湖水如镜"),
    Landmak(name: "草原", detail: "离离原上草"),
    Landmak(name: "非洲", detail: "看山是山"),
    Landmak(name: "海角", detail: "仗剑走天涯"),
    Landmak(name: "青山", detail: "青山留不住"),
    Landmak(name: "雪山", detail: "雪山铁甲寒")
]


struct LandmarkRow: View {
    var body: some View {
        List(landmarks) { item in
            HStack{
                Image(item.thumbnailName)
                VStack(alignment: .leading) {
                    Text(item.name)
                    Text(item.detail)
                        .font(.subheadline)
                        .foregroundColor(Color.secondary)
                }
            }
        }
    }
}

//然后美化页面,并且添加按钮(进入子页面)功能
struct LandmarkRow: View {
    var body: some View {
        NavigationView{
            List(landmarks) { item in
                HStack{

                    // 功能:点击进入子页面
                    NavigationLink(destination:Text(item.name)){
                        // cornerRadius:图片变成圆角
                        Image(item.thumbnailName).cornerRadius(10.0)
                        VStack(alignment: .leading) {
                            Text(item.name)
                            Text(item.detail)
                                .font(.subheadline)
                                .foregroundColor(Color.secondary)
                        }
                    }

                }
                //加上标题,这个标题归属于 List
            }.navigationBarTitle(Text("景色"))
        }

    }
}

子页面

  • 正向传值
  • 点击后缩放
  • 缩放过程中有过渡动画效果
struct LandmarkDetail: View {
    let landmark:Landmak
    //实现点击后放大和缩小功能
    // struct 是不可改变的,加上 @State 后可改变,改变后会刷新整个页面
    // 所以后面 onTapGesture 后,zoomed 改变了,就重新刷新整个页面了
    @State private var zoomed=false // 一般用 private 修饰
    var body: some View {
        Image(landmark.imageName)
            .resizable()// 缩放到适应屏幕大小,否则就按照原像素显示
        // aspectRatio:保持图片比例;
        //.fill:图片多的部分被截断;
        //.fit 图片缩小到不会被截断
            .aspectRatio(contentMode: zoomed ? .fill : .fit)
        //navigation,默认在左上角,用 .inline 放到标题上
            .navigationBarTitle(Text(landmark.name),displayMode: .inline)
        //用户点击事件
            .onTapGesture {
                //withAnimation:增加动画效果
                withAnimation(){
                    //上面写了,改这个后会重新刷新整个页面
                    self.zoomed.toggle()
                }
            }

        Text(landmark.detail)
            .font(.largeTitle)
            .foregroundColor(.secondary)
        //同样增加动画
            .transition(.move(edge: .trailing))

    }
}


//这个用来调试
struct LandmarkDetail_Previews: PreviewProvider {
    static var previews: some View {
        //因为是套在父navigation里面的,所以预览不展示(但实际有效果)
        //要像展示,用NavigationView 包起来:
        NavigationView{
            LandmarkDetail(landmark: landmarks[0])
        }
    }
}

地图

// 主要代码
import SwiftUI
import MapKit

struct MapView: View {
    @State private var region=MKCoordinateRegion(
        center:CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.116_868),
        span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
    )

    var body: some View {
        Map(coordinateRegion: $region)
    }
}


//如何调用它:
MapView()
    .ignoresSafeArea(edges: .top) //上方顶到头
    .frame(height:300) // 定义高度

如何改名/icon

有个 Info.plits->Bundle Display Name

如何调包

例如,我像调这个包:https://github.com/kirualex/SwiftyGif

  1. 安装 https://github.com/Carthage/Carthage brew install carthage
  2. touch Cartfile,然后黏贴 github "kirualex/SwiftyGif"
  3. carthage update --use-xcframeworks

您的支持将鼓励我继续创作!