当前位置:网站首页>Swiftui 2.0 course notes Chapter 4
Swiftui 2.0 course notes Chapter 4
2022-06-23 05:14:00 【Alten wood】
Course link :https://www.bilibili.com/video/BV1q64y1d7x5?p=4
Course project warehouse :https://github.com/cnatom/MemorizeSwiftUI
List of articles
enumeration enum
stay enum in , We can use another enum.enum Variables in , The preceding parameters may not specify a label , Like the one below drink label
enum FastFoodMenuItem{
case hamburger(numberOfPatties: Int)
case fries(size: FryOrderSize)
case drink(String, ounces: Int)
case cookie
}
enum FryOrderSize{
case large
case small
}
enum Variable definitions
let menuItem: FastFoodMenuItem = FastFoodMenuItem.hamburger(numberOfPatties: 2)
var otherItem: FastFoodMenuItem = .cookie // amount to FastFoodMenuItem.cookie
according to enum type , Execute different statements
var menuItem = FastFoodMenuItem.hamburger(numberOfPatties: 2)
switch menuItem {
case FastFoodMenuItem.hamburger : print("burger")
case FastFoodMenuItem.fries: print("freis")
case FastFoodMenuItem.drink: print("drink")
case FastFoodMenuItem.cookie : print("cookie")
}
Maybe , The compiler knows menuItem Enumerate the types of variables , So we can also write more simply
var menuItem: FastFoodMenuItem = FastFoodMenuItem.hamburger(numberOfPatties: 2)
switch menuItem {
case .hamburger : print("burger")
case .fries: print("freis")
case .drink: print("drink")
case .cookie : print("cookie")
}
Swift Also support default, The following code ,s neither "goodbye" Neither "hello", So we can only execute default The statement in
let s: String = "helloworld"
switch s{
case "goodbye": ...
case "hello": ...
default: ...
}
case Multiple statements can be added later , And you don't need to use break keyword
var menuItem: FastFoodMenuItem = FastFoodMenuItem.hamburger(numberOfPatties: 2)
switch menuItem {
case .hamburger : print("burger")
case .fries:
print("freis")
print("yummy")
case .drink:
print("drink")
case .cookie : print("cookie")
}
You can also get the value of an item in the enumeration type
let menuItem = FastFoodMenuItem.drink("Coke", Int,ounces: 32)
switch menuItem {
case .hamburger(let numberOfPatties):print("\(numberOfPatties)")
case .fries(let size):print("\(size)")
case .drink(let brand, let ounces):print("\(brand) + \(ounces)")
case .cookie:print("a cookie!")
}
enum You can also add functions to
enum FastFoodMenuItem{
case hamburger(numberOfPatties: Int)
case fries(size: FryOrderSize)
case drink(String, Int,ounces: Int)
case cookie
func isDrink(number: Int) -> Bool{
switch self {
case .hamburger(let pattyCount): return pattyCount == number
case .fries, .cookie : return true
case .drink(_, let ounces): return ounces == 16
}
}
}
optional type Optional
Swift Optional for (Optional) type , Used to handle missing values . Its essence is an enumeration type
enum Optional<T>{
case none
case some(T)
}
// The following groups of statements are equivalent
var hello: String?
var hello: Optional<String> = .none
var hello: String? = "hello"
var hello: Optional<String> = .some("hello")
var hello: String? = nil
var hello: Optional<String> = .none
Add an exclamation point after the variable (hello!), Meaning for Compulsory unpacking , This method is usually not advisable .
enum Optional<T>{
case none
case some(T)
}
let hello: String? = ...
// Compulsory unpacking , And below switch The basic equal
print(hello!) // If the variable is empty , Throws an error
switch hello{
case .none: // Throw an error
case .some(let data): print(data)
}
Generally, conditional statements are used to determine whether a variable is empty .
let hello: String? = ...
// The usual way of writing ( Equivalent to... Below switch)
if let safehello = hello{
print(safehello)
} else {
// do something else
}
switch hello{
case .none: {
// do something else
}
case .some(let data): print(data)
}
?? Operator can be set for a variable " Optional default "
let x: String? = ...
let y = x ?? "foo" // If x It's empty , be y="foo"
// The above statement is the same as the following
switch x{
case .none: y = "foo"
case .some(let data): y = data
}
Using a single ? It can judge the null of multiple variables and take values (Optional chaining)
let x: String? = ...
let y = x?.foo()?.bar?.z // y Equal to the value corresponding to the first non empty variable from left to right
// If all values are empty , be y Also empty
Updated MVVM example
Model
//
// MemoryGame.swift
// Memorize
//
// Created by atom on 2022/5/21.
//
import Foundation
//Model
//where CardContend: Equatable bring CardContent You can use ==
struct MemoryGame<CardContend> where CardContend: Equatable{
//private(set) Read only
private(set) var cards: Array<Card>
private var indexOfFaceUp: Int? // Front up card index
init(numberOfPairsOfCards: Int,createCardContent: (Int) -> CardContend){
cards = Array<Card>()
for pairIndex in 0..<numberOfPairsOfCards{
let content = createCardContent(pairIndex)
cards.append(Card(content: content, id: pairIndex*2))
cards.append(Card(content: content, id: pairIndex*2+1))
}
}
// mutating Enable this function to change struct The variable of
mutating func choose(_ card: Card){
// Get the... Of the selected card Index, Make sure the card is facing up ( To prevent repeated clicks , This causes the card to keep turning ), Make sure the card is not matched
if let chosenIndex = cards.firstIndex(where: {
$0.id == card.id}),
cards[chosenIndex].isFaceUp==false,
cards[chosenIndex].isMatched==false
{
if let potentialMatchIndex = indexOfFaceUp {
// If the second open card
if cards[chosenIndex].content == cards[potentialMatchIndex].content{
// It is the same as the first opened card , Then the two match successfully
cards[chosenIndex].isMatched = true
cards[potentialMatchIndex].isMatched = true
}
// After matching successfully , There is currently no card facing up
indexOfFaceUp = nil
}else{
// If it is the first card opened , Then the cards that have been turned to the front should be turned to the back
for index in cards.indices {
cards[index].isFaceUp = false
}
indexOfFaceUp = chosenIndex
}
cards[chosenIndex].isFaceUp.toggle() // Turn the card upside down ,toggle It's equivalent to taking the opposite a = !a
}
}
// obtain card The first index of , This function is similar to the built-in function cards.firstIndex(where:{}) The effect is equal to
// func index(of card:Card)->Int?{
// for index in 0..<cards.count{
// if(cards[index].id==card.id){
// return index
// }
// }
// return nil // because Int?, So here we can return a nil
// }
//MemoryGame<CardContent>.Card
//Identifiable: Make every one Card unique , Can be Foreach Unique identification
struct Card: Identifiable{
var isFaceUp: Bool = false
var isMatched: Bool = false
var content : CardContend
var id: Int
}
}
ViewModel
import SwiftUI
//ViewModel
//ObservableObject bring @Published When the decorated variable changes , Will send UI Refresh announcement
class EmojiMemoryGame: ObservableObject{
//static The initialization order of type variables is in normal var Before
// therefore static Class members of can be used as default values for other class members
// Such as var a = EmojiMemoryGame.emojis[1]
static var emojis = ["","🦴","","","","","","","","",
"","","","","","","","","🥩",""]
// Create a Model
static func createMemoryGame() -> MemoryGame<String> {
return MemoryGame<String>(numberOfPairsOfCards: 3, createCardContent: {
// In the definition :createCardContent: (Int) -> CardContend //CardContend It's a generic
// therefore , The type is automatically recognized here , take
// index in Identified as (index: Int) -> String in
index in
return EmojiMemoryGame.emojis[index]
} )
}
// @Published bring model Every time it changes , Will send UI Refresh announcement objectWillChange.send()
@Published private var model: MemoryGame<String> = createMemoryGame()
var cards: Array<MemoryGame<String>.Card>{
return model.cards
}
// MARK: - Intent(s)
// towards Model Send from View Received instructions
func choose(_ card: MemoryGame<String>.Card){
//objectWillChange.send()
model.choose(card)
}
}
View
import SwiftUI
struct ContentView: View {
// @ObservedObject send View track viewModel And refresh UI
@ObservedObject var viewModel: EmojiMemoryGame
var body: some View {
ScrollView {
LazyVGrid(columns:[GridItem(.adaptive(minimum: 65))]){
ForEach(viewModel.cards){
card in
MyCardView(card: card)
.aspectRatio(2/3,contentMode: .fit)
.onTapGesture {
// View towards ViewModel Send changes Model The notice of
viewModel.choose(card)
}
}
}
}
.foregroundColor(.blue)
.padding()
}
}
struct MyCardView: View{
let card: MemoryGame<String>.Card
var body: some View{
ZStack{
let shape = RoundedRectangle(cornerRadius: 20)
if card.isFaceUp{
// On the face
shape.fill().foregroundColor(.white)
shape.strokeBorder(lineWidth: 3)
Text(card.content).font(.largeTitle)
}else if card.isMatched{
// Successfully matched cards
shape.opacity(0)
}else{
// Facing up on the opposite side
shape.fill()
}
}
}
}
// Xcode preview UI
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let game = EmojiMemoryGame()
ContentView(viewModel: game).preferredColorScheme(.light)
ContentView(viewModel: game).preferredColorScheme(.dark)
}
}
边栏推荐
- 【C语言】关键字
- 3 天完成小学期项目,手把手教你完成天气播报系统!
- 微信小程序:微信也可以发闪照了闪照制作生成微信小程序源码下载,自定义闪照时间
- Official download and installation of QT and QT vs tools plug-ins
- JSP入门级笔记
- 微信小程序:凑单满减计算神器
- MVVM has become history, and Google has fully turned to MVI
- Wechat applet example development: run
- UnityShader入门精要——Unity中的渲染优化技术(四)
- 直接插入排序——【常见排序法(1/8)】
猜你喜欢

Hard core, become a high-quality tester: learn to communicate with products

【Laravel系列7.8】广播系统

Strong push, quick start to software testing

Arduino温湿度传感器DHT11(含代码)

Visual display of TEQC quality analysis results using teqcplot

HCIP 交换机实验

Dolphin scheduler 2.0.5 spark task test summary (source code optimization)

Dolphin scheduler 2.0.5 task test (spark task) reported an error: container exited with a non zero exit code 1

功能测试人员如何做到花一个月的时间进阶自动化软件测试工程师

Jetpack Compose 从开门到入门之 MenuBar桌面菜单(Desktop Menu)
随机推荐
【Proteus仿真】Arduino UNO+PCF8574+LCD1602+MPX4250电子秤
HCIP第五次作业
开源生态|超实用开源License基础知识扫盲帖(下)
Parameter passing of 18 generator function
OSPF分流实验
In unity, how to read and write a scriptableobject object in editor and runtime
One or more lines of text overflow, ellipsis instead
[MAC] there is no source option in security and privacy
rtklib新版本2.4.3 b34测试对比
Separate use of alertmanager alarms and use of Prometheus configuration alarm rules
大環境不好難找工作?三面阿裏,幸好做足了准備,已拿offer
104. 简易聊天室7:使用 Socket 传递对象
Beyond chips and AI, why is hard technology capital becoming more and more "hard core"?
AlertManager告警的单独使用及prometheus配置告警规则使用
掌握 Shell,一篇就够了!
UI自动化定位利器-xpath实战
Implementation of the rotation chart
3 天完成小学期项目,手把手教你完成天气播报系统!
MVVM has become history, and Google has fully turned to MVI
Direct insertion sort - [common sort method (1/8)]