섹션17: SwiftUI and Declarative Programming, Project Catalyst, 명함 만들기 (복습)

인생노잼시기·2021년 2월 22일
0

📱Udemy iOS

목록 보기
10/20

SwiftUI란?

declarative Swift code로 만들어진 UI 프레임워크

  • Drag and Drop to Create Code
  • Easy Layouts VHZ Stack
  • Highly Reusable UI
  • Live Preview
  • Cross apple Platform
    Project Catalyst
  • iOS13, iPhone 6S 이후

XCode 사용법

command ]

들여쓰기 정리


I Am Rich 프로젝트

File > New > Project
프로젝트를 만들 때 swiftui delegate로 만들면 scene delegate파일이 안보인다

https://flatuicolors.com/ 커스텀 색상
https://www.uicolor.io/#/hex-to-ui 16진수에서 rgb로 변경
https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/ SFsymbols

폰트 추가


레이블에 드래그하기

배경 색상 추가

프로젝트 우클릭 > New Group > fonts > .ttf 추가
Font.custom("", size: <#T##CGFloat#>)

Edges Ignoring Safe Area

백그라운드 화면에 safe area 안에만 색이 입혀졌는데
그 밖에도 추가하려고 사용

이미지 크기 저장

Image Resizable

struct ContentView: View {
    var body: some View {
        ZStack {
            Color(.systemTeal).edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
            VStack {
                Text("I Am Rich")
                    .font(.system(size: 40))
                    .fontWeight(.bold)
                    .foregroundColor(Color.white)
                    .padding()
                Image("diamond")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 200, height: 200, alignment: .center)
            }
        }
        
    }
}

명함 만들기

색 조합 추천 사이트

hex코드
https://flatuicolors.com
hext코드 -> UIColor
https://www.uicolor.io/#/hex-to-ui

폰트

https://fonts.google.com

Fonts폴더그룹 생성하고
다운받은 파일(NotoSansKR-Regular.otf) 집어넣기

info.plist에 추가
Fonts provided by application
Item 0 Sanserif.ttf

클립

Clip Shape

overlay

뷰 위에 뷰 추가하기

command click


extract subview

InfoView.swift 파일을 생성하고 재사용할 수 있게 만들기

import SwiftUI

struct InfoView: View {
    let text: String
    let imageName: String
    
    var body: some View {
        RoundedRectangle(cornerRadius: 30)
            .fill(Color.white)
            .frame(height: 50)
            .overlay(HStack {
                Image(systemName: imageName)
                    .foregroundColor(Color.green)
                Text(text)
            })
            .padding(.all)
    }
}

struct InfoView_Preview: PreviewProvider {
    static var previews: some View {
        InfoView(text: "Hello", imageName: "phone.fill")
            .previewLayout(.sizeThatFits)
    }
}
//  ContentView.swift

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            
            Color(red: 0.18, green: 0.80, blue: 0.44)
                .edgesIgnoringSafeArea(.all)

            VStack {
                Image("angela")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 150, height: 150)
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.white, lineWidth: 5))
                Text("안젤라")
                    .font(Font.custom("NotoSansKR-Regular.otf", size: 40))
                    .fontWeight(.bold)
                    .foregroundColor(Color.white)
                    .padding()
                Text("iOS Developer")
                    .font(.system(size: 25))
                    .foregroundColor(Color.white)
                
                Divider()
                
                InfoView(text: "angela@gmail.com", imageName: "evnvelope.fill")
            }
            
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Bug Alert!

Text Not Displaying Correctly in Dark Mode
.foregroundColor(Color("Info Color"))


Dice-SwiftUI

주사위 던지기 게임 swiftUI로 만들기

@State

managing state in SwiftUI

  • structure
  • immutability of structure

struct 안에서 property를 변경하면
old copy는 destroy되고 new copy가 대체한다
SwiftUI에서는 특별한 wrapper @State를 붙여주면
property의 변경사항을 체크해서 ContentView를 rebuild한다

  • mutating func
  • @State property
//  ContentView.swift

import SwiftUI

struct ContentView: View {
    
    //variable이 변경되면 ContentView를 새로 생성
    @State var leftDiceNumber = 1
    @State var rightDiceNumber = 2
    
    var body: some View {
        
        ZStack {
            Image(/*@START_MENU_TOKEN@*/"background"/*@END_MENU_TOKEN@*/)
                .resizable()
                .edgesIgnoringSafeArea(.all)
            VStack {
                Image("diceeLogo")
                
                Spacer()
                
                HStack {
                    DiceView(n: leftDiceNumber)
                    DiceView(n: rightDiceNumber)
                }
                .padding(.horizontal)
                
                Spacer()
                
                Button(action: {
                    self.leftDiceNumber = Int.random(in: 1...6)
                    self.rightDiceNumber = Int.random(in: 1...6)
                }) {
                    Text("Roll")
                        .font(.system(size: 50))
                        .fontWeight(.bold)
                        .foregroundColor(Color.white)
                        .padding(.horizontal)
                }
                .background(Color.red)
            }
        }
    }
}

struct DiceView: View {
    
    let n: Int
    
    var body: some View {
        Image("dice\(n)")
            .resizable()
            .aspectRatio(1, contentMode: .fit)
            .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


Hacker News

https://news.ycombinator.com/

algolria API

https://hn.algolia.com/api

Identifiable protocol

id라는 String형식의 변수가 필요

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            List(posts) { post in
                Text(post.title)
            }
            .navigationBarTitle("H4X0R NEWS")
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Post: Identifiable {
    let id: String
    let title: String
}

let posts = [
    Post(id: "1", title: "Hello"),
    Post(id: "2", title: "Bye"),
    Post(id: "3", title: "Chao")
]

Observer Design Pattern

Observer Design Pattern + Networking

broadcast one or many of its properties to andy interested parties

@Published var posts = Post (notify all of the listeners)
RSS 피드와 비슷하다
posts를 subscribe하면 콘텐츠가 바뀔 때 hear한다

@ObservedObject var networkManager = NetworkManager()
set up a property as a listener (리스너 설정한다)

posts를 publish하고 업데이트가 되면 리스너에서 즉시 알아챈다

//ContentView.swift

import SwiftUI

struct ContentView: View {
    
    @ObservedObject var networkManager = NetworkManager()
    
    var body: some View {
        NavigationView {
            List(networkManager.posts) { post in
                HStack {
                    Text(String(post.points))
                    Text(post.title)
                }
            }
            .navigationBarTitle("H4X0R NEWS")
        }
        .onAppear(perform: {
            self.networkManager.fetchData()
        })
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
//NetworkManager.swift

import Foundation

class NetworkManager: ObservableObject {
    
    @Published var posts = [Post]()
    
    func fetchData() {
        if let url = URL(string: "http://hn.algolia.com/api/v1/search?tags=front_page") {
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { (data, response, error) in
                if error == nil {
                    let decoder = JSONDecoder()
                    if let safeData = data {
                        do {
                            let results = try decoder.decode(Results.self, from: safeData)
                            //💥주의
                            DispatchQueue.main.async {
                                self.posts = results.hits
                            }
                        } catch {
                            print(error.localizedDescription)
                        }
                    }
                    
                }
            }
            task.resume()
        }
        
    }
}
//PostData.swift

import Foundation

struct Results: Decodable {
    let hits: [Post]
}

struct Post: Decodable, Identifiable {
    var id: String {
        return objectID
    }
    let objectID: String
    let points: Int
    let title: String
    let url: String?
}

WKWebView

SwiftUI View 파일 생성 -> DetailView.swift

//NavigationLink로 이동 가능해진다
//ContentView.swift

NavigationView {
            List(networkManager.posts) { post in
                NavigationLink(destination: DetailView(url: post.url)) {
                    HStack {
                        Text(String(post.points))
                        Text(post.title)
                    }
                }
            }
            .navigationBarTitle("H4X0R NEWS")
        }
//DetailView.swift

import SwiftUI

struct DetailView: View {
    
    let url: String?
    
    var body: some View {
        WebView(urlString: url)
    }
}

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(url: "https://www.google.com")
    }
}
//재사용하기 위해 분리
//SwiftUI는 아직 WebKit가 없어서 가져와서 만들어주기
//WebView.swift

import Foundation
import SwiftUI  //💥
import WebKit

struct WebView: UIViewRepresentable {
    let urlString: String?
    
    func makeUIView(context: Context) -> WKWebView {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        if let safeString = urlString {
            if let url = URL(string: safeString) {
                let request = URLRequest(url: url)
                uiView.load(request)
            }
        }
    }
}

Project Catalyst 캐털리스트

Marzipan 마지팬
아이폰과 아이패드에 사용하는 앱을 맥에서 사용할 수 있게 하자
iOS 앱을 빌드하는데 사용하는 UIKit 프레임워크를 맥으로 가져오자

프로젝트 클릭 > Target > Mac 체크
Signing&Capabilities > signing
https://developer.apple.com/documentation/uikit/mac_catalyst

Xcode 사용법

command option p 프리뷰

profile
인생노잼

2개의 댓글

comment-user-thumbnail
2021년 8월 3일

211 - 221

답글 달기