본문 바로가기

프로젝트

(86)
TintTrove [Privacy Policy] Privacy Policy MinKyu CHA built the TintTrove app as a Free app. This SERVICE is provided by MinKyu CHA at no cost and is intended for use as is. This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service. If you choose to use my Service, then you agree to the collection and use of information in..
JusTheme [Privacy Policy] Privacy Policy MinKyu, CHA built the JusTheme app as a Free app. This SERVICE is provided by MinKyu, CHA at no cost and is intended for use as is. This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service. If you choose to use my Service, then you agree to the collection and use of information i..
06. 더 나아가기 더 나아가기 | 난이도 선택하기, 개선하기 강의는 끝났지만 난이도를 선택하는 부분은 빠져있다. enum FastingPlan: String { case beginner = "12:12" case intermediate = "16:8" case advanced = "20:4" var fastingPeriod: Double { switch self { case .beginner: return 12 case .intermediate: return 16 case .advanced: return 20 } } } beginner와 intermediate, advance를 화면에서 직접 선택할 수 있도록 추가로 구현한다. 난이도 선택하기 | 인터페이스 구성하기 현재 앱의 화면은 위와 같고, 난이도를 선택하기 위해 다..
05. 기능 구현 #3 기능 구현 #3 | Upcoming time, Percentage, 실제 시간 반영하기 Upcoming time 타이머의 상태가 notStarted이면 elapsedTime과 remainingTime을 표시하는 것은 부자연스럽다. 선택된 난이도에 따라서 현재시간을 기준으로 다음 식사 시간을 나타내도록 수정한다. // MARK: Timer VStack(spacing: 30) { // MARK: Upcoming Time if fastingManager.fastingState == .notStarted { VStack(spacing: 5) { Text("Upcoming fast") .opacity(0.7) Text("\(fastingManager.fastingPlan.fastingPeriod, specifie..
04. 기능 구현 #2 기능 구현 #2 | Timer 구현 Timer 구현 | fastingTime, feedingTime 계산하기 class FastingManager: ObservableObject { @Published private(set) var fastingState: FastingState = .notStarted @Published private(set) var fastingPlan: FastingPlan = .intermediate @Published private(set) var startTime: Date @Published private(set) var endTime: Date var fastingTime: Double { return fastingPlan.fastingPeriod } var feeding..
03. 기능 구현 #1 기능 구현 #1 | FastingManager FastingManager | FastingState FastingManager는 본격적인 식단 관리 기능의 구현에 해당한다. FastingManager라는 이름의 파일을 새로 생성해 구현한다. import Foundation class FastingManager: ObservableObject { } ObservableObject 프로토콜을 채용한 클래스의 형태로, 해당 해당 클래스에 접근하는 View가 Published로 지정된 속성을 사용할 수 있게 된다. import Foundation enum FastingState { case notStarted case fasting case feeding } class FastingManager: Observa..
02. 인터페이스 디자인 #2 인터페이스 디자인 #2 ContentView ContentView | Header body의 가독성을 높이기 위해 구성되는 View들은 extension으로 구현한다. header는 현재 상태를 문장으로 표시하기 위한 TextView와 이후 Fasting Plan을 변경하는 버튼을 포함한다. struct ContentView: View { var body: some View { VStack { header ProgressRing() } } } extension ContentView { // MARK: Title, Fasting Plan var header: some View { VStack { Text("Let's get started!") .font(.headline) .foregroundColor(C..
01. 인터페이스 디자인 #1 인터페이스 디자인 #1 ProgressRing, Timer ProgressRing ProgressRing은 총 진행상황을 표시할 PlaceHolder와 현재 진행 상황을 표시할 진행링 두 개의 View의 조합이다. 같은 좌표에 겹쳐 표시돼야 하므로 ZStack으로 구현한다. struct ProgressRing: View { @State var progress = 0.0 var body: some View { 우선 진행 상태를 나타낼 변수를 하나 정의한다. var body: some View { ZStack { // MARK: Placholder Ring Circle() .stroke(lineWidth: 20) .foregroundColor(Color(UIColor.systemGray)) .opacity(..
00. 시작하며 이제 막 UIKit에 대한 공부를 마치고 작은 프로젝트를 진행하던 작년에 이야기다. 작은 프로젝트를 몇 개 해 봤지만 여전히 개념들은 어려웠고, 특히나 만들려고 했던 인터벌 타이머는 thread 분리와 함께 완전히 박살났다. 1초 간격으로 실행 돼야 할 코드가 어느 때는 0.5초 만에, 어느 때는 1초가 넘어서 동작하니 제대로 된 기능을 한다고 볼 수 없다. 올해는 SwiftUI를 배웠고, 다시 이전의 프로젝트를 재시동 하기 전에 시계나 타이머에 관한 프로젝트를 몇 개 해 보고자 한다. 이번에 만들어 보는 FastingTimer는 식단 관리 앱이다. 원형의 Indicator를 가지고 진행 상황을 알려주고, 매 초 업데이트 되니 내가 구현하려던 매커니즘과 동일하다고 할 수 있다. 앱 Swift Swift ..
26. 기본 UI 구현하기 #9 기본 UI 구현하기 #9 프로필 수정 버튼 표시하기 ProfileView에는 EditProfile 버튼이 존재한다. 지금은 본인의 Profile인지 상대방의 Profile인지 구분 없이 Edit Profile을 표시하지만, 이 둘을 구분해 Follow 버튼으로 치환해 표시할 수 있도록 구현해 본다. class ProfileViewModel: ObservableObject { @Published var tweets = [Tweet]() @Published var likedTweets = [Tweet]() private let service = TweetService() private let userService = UserService() let user: User init(user: User) { sel..