WWDC2019: SwiftUI achieve your first App

System: Mac OS 10.15.1, XCode 11.2.1, swift 5.0
Writing Time: 2019-11-26

Explanation

This article code implementation WWDC2019 video Introducing SwiftUI: Building Your First App , improvement is achieved with XCode 11.2.1, the contents of the video is to be implemented on XCode 11 beta, has been abandoned some api.

running result:
Here Insert Picture Description
Here Insert Picture Description

Creating SwiftUI engineering, as well as a new class SwiftUI

New Project, named RoomWWDC204.
For details, see SwiftUI combat: monopolized the new framework

Creating Model

The data SwiftUI in the first class citizens here to create a data type Room

import SwiftUI

struct Room: Identifiable {
    var id = UUID()
    var name: String
    var capacity: Int
    var hasVideo: Bool = false
    
    var imageName: String {
        return name
    }
    var thumbnailName: String {
        return name  + "Thumb"
    }
    
}

#if DEBUG
let testData = [
    Room(name: "room-1", capacity: 6, hasVideo: true),
    Room(name: "room-2", capacity: 8, hasVideo: false),
    Room(name: "room-3", capacity: 16, hasVideo: true),
    Room(name: "room-4", capacity: 10, hasVideo: true),
    Room(name: "room-5", capacity: 12, hasVideo: false),
    Room(name: "room-6", capacity: 8, hasVideo: false),
    Room(name: "room-7", capacity: 10, hasVideo: true),
    Room(name: "room-8", capacity: 7, hasVideo: false),
    Room(name: "room-9", capacity: 1, hasVideo: false),
]

#endif

Resolution:

  • id: Object that uniquely identifies
  • name: the name of the picture
  • capacity: Room capacity
  • hasVideo: whether it is video conferencing
  • imageName: picture name
  • thumbnailName: Thumbnails name

Observer data

In order to implement CRUD data, data can be passed down layer by layer.
Create a class RoomStore

import SwiftUI
import Combine
import Foundation

class RoomStore: ObservableObject {
    
    @Published var rooms: [Room]
    
    init(rooms: [Room]) {
        self.rooms = rooms
    }
    
}

Details page

New Cell page RoomDetail,

import SwiftUI

struct RoomDetail: View {
    let room: Room
    @State private var zoomed = false
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            Image(room.imageName)
                .resizable()
                .aspectRatio(contentMode: zoomed ? .fill : .fit)
                .navigationBarTitle(Text(room.name), displayMode: .inline)
                .onTapGesture {
                    withAnimation(.easeInOut(duration: 2)) {
                        self.zoomed.toggle()
                    }
                }
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
            
            if room.hasVideo && !zoomed {
                Image(systemName: "video.fill")
                    .font(.title)
                    .padding(.all)
                    .transition(.move(edge: .leading))
            }
        }
    }
}

#if DEBUG
struct RoomDetail_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            NavigationView {
               RoomDetail(room: testData[0])
            }
            NavigationView {
               RoomDetail(room: testData[1])
            }
        }
    }
}
#endif

Resolution:

  • ZStack: Z-axis perpendicular to the direction of the container, put a layer below the large image, the upper left corner of the top layer to put the camera.
  • resizable: Picture Scalable
  • aspectRatio: scaling (fill stretching picture screen, fit or scaled down to show all)
  • navigationBarTitle: navigation bar text
  • onTapGesture: Click Event
  • withAnimation: Animation
  • transition: transition animation

这个页面可以单独预览(快捷键: Command + Option + p), 这里用Group可以同时预览两个页面。
第一个hasVideo = true, 左上角有摄像头。Here Insert Picture Description
第二个hasVideo = false. 左上角有没有摄像头。
Here Insert Picture Description
@State根据属性去控制界面self.zoomed.toggle()
Here Insert Picture Description
数据流

数据权限 Source of Truth Derived Value
只读 Constant Property
读写 @State
ObservableObject
@ObservedObject

主界面List视图

tableview在这里就是List

//
//  ContentView.swift
//  RoomWWDC204
//
//  Created by zgpeace on 2019/11/24.
//  Copyright © 2019 zgpeace. All rights reserved.
//

import SwiftUI

struct ContentView: View {
    @ObservedObject var store = RoomStore(rooms: [])
    
    var body: some View {
        NavigationView {
//            List(store.rooms) { room in
            List {
                Section {
                    Button(action: addRoom) {
                        Text("Add Room")
                    }
                }
                
                Section {
                    ForEach(store.rooms) { room in
                        RoomCell(room: room)
                    }
                    .onDelete(perform: delete)
                    .onMove(perform: move)
                }
            }
            .navigationBarTitle(Text("Rooms"))
        .navigationBarItems(trailing: EditButton())
            .listStyle(GroupedListStyle())
        }
    
    }
    
    func addRoom() {
        store.rooms.append(Room(name: "Hall 2", capacity: 2000))
    }
    
    func delete(at offsets: IndexSet) {
        store.rooms.remove(atOffsets: offsets)
    }
    
    func move(from source: IndexSet, to destination: Int) {
        store.rooms.move(fromOffsets: source, toOffset: destination)
    }
}

struct RoomCell: View {
    let room: Room
    
    var body: some View {
        NavigationLink(destination: RoomDetail(room: room)) {
            Image(room.thumbnailName)
                .cornerRadius(8)
            VStack(alignment: .leading) {
                Text(room.name)
                Text("\(room.capacity) people")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView(store: RoomStore(rooms: testData))
            
            ContentView(store: RoomStore(rooms: testData))
                .environment(\.sizeCategory, .extraExtraExtraLarge)
            
            ContentView(store: RoomStore(rooms: testData))
                .environment(\.colorScheme, .dark)
            
            ContentView(store: RoomStore(rooms: testData))
            .environment(\.layoutDirection, .rightToLeft)
        }
    }
}
#endif

解析:

  • listStyle: tableview的展示样式,比如这里就用GroupedListStyle()样式
  • onDelete: 可删除
  • onMove: 可移动

运行效果:
图片展示的是group里的第三种,黑暗模式ContentView(store: RoomStore(rooms: testData)) .environment(\.colorScheme, .dark)

Here Insert Picture Description

SwiftUI优势解析

以前用UIKit的时候 Controller是控制中心,数据流比较复杂. 导致Controller膨胀很大。
Here Insert Picture Description
导致UI Bugs出现不可控
Here Insert Picture Description
事件状态转换、调用相当频繁
Here Insert Picture Description
导致页面跟数据不同步
Here Insert Picture Description

SwiftUI 只有body struct, 把状态统一为一种类型
Here Insert Picture Description
Here Insert Picture Description

SwiftUI是最快速构建伟大App的新框架
Here Insert Picture Description

总结

细节请移步WWDC,WWDC的讲解包括UI的交互和原理。
推荐Mac观看WWCD的软件:WWDC for macOS

代码下载

https://github.com/zgpeace/RoomWWDC204/tree/master

参考

WWDC
https://developer.apple.com/videos/play/wwdc2019/204/

Courseware Download
https://devstreaming-cdn.apple.com/videos/wwdc/2019/204isgnpbqud244/204/204_introducing_swiftui_building_your_first_app.pdf

https://www.raywenderlich.com/3868932-wwdc-2019-top-10-videos

https://wwdc.io/

Published 127 original articles · won praise 12 · views 20000 +

Guess you like

Origin blog.csdn.net/zgpeace/article/details/103250220