数据类型
- 变量用 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
- 安装 https://github.com/Carthage/Carthage
brew install carthage
touch Cartfile
,然后黏贴github "kirualex/SwiftyGif"
carthage update --use-xcframeworks