게시글
질문&답변
2024.10.02
Apple 공식 문서 보는법
안녕하세요 이재영 님.애플 공식문서 조회 하는 것에 대해서 몇가지 저의 팁을 드리자면 https://developer.apple.com/documentation/애플 문서는 주제별로 잘 정리되어 있지만, 특정 기능을 바로 찾기 위해서는 먼저 개념 파악이 중요합니다. 예를 들어, SwiftUI에서 뷰를 다룬다면 “View Protocol”로 검색을 시작하는 것이 유용합니다. 키워드 간결화: 문서 검색은 구체적인 용어를 간단하게 입력할수록 정확한 결과를 얻을 수 있습니다. 예를 들어 “SwiftUI delete text items in loop”보다는 “SwiftUI List delete”처럼 핵심 단어로 줄여서 검색해보세요.메서드 이름, 프로토콜 사용: Swift나 SwiftUI에서 제공하는 메서드나 프로토콜 이름을 직접 검색하면 유용합니다. 예를 들어, “ForEach”를 이용한 반복 처리를 문서에서 찾아보고, 그 예시를 통해 구현 방법을 이해할 수 있습니다.예를 들어, 반복문을 통해 텍스트를 한 번에 지우는 기능을 찾고자 한다면:• 먼저 “SwiftUI ForEach”를 검색합니다. 이 반복문 구조에 대한 문서를 찾고, ForEach 내부에서 데이터를 처리하는 방법을 이해할 수 있습니다.• 그다음으로 “SwiftUI delete items”나 “SwiftUI onDelete”와 같은 키워드로 검색합니다. SwiftUI의 List에서 항목을 삭제하는 기능은 주로 onDelete() 메서드로 처리합니다.• 이때 관련 문서를 찾으면, 다양한 예제와 함께 사용법을 배울 수 있습니다. 예를 들어, ForEach와 onDelete()를 결합하면 리스트의 여러 텍스트 항목을 반복적으로 삭제하는 기능을 구현할 수 있습니다.SwiftData 강의 부분은 오늘이나 내일 중으로 업데이트 예정입니다.감사합니다.Jacob
- 0
- 2
- 60
질문&답변
2024.06.28
5월 업데이트 예정이었던 , iOS17 컨텐츠 SwifData 업데이트 언제 되나요 ?
안녕하세요 랑프님.제가 개인적인 사정으로인해서 업데이트가 지연되고 있습니다. 7월 중으로 최대한 빨리 SwiftData 부분 강의 업로드 하겠습니다. 양해 부탁드립니다. 감사합니다.
- 0
- 1
- 124
질문&답변
2024.06.28
GalleryView 작성시, @State? @Bidnable? 의 차이점이 뭔지 궁금합니다.
안녕하세요 ycc3819 님제가 확인이 늦어 이제 답변드리네요 죄송합니다.질문주신 부분과 링크에서 나타난 것은 @State와 @Observable을 함께 사용할 때 주의할 점은 다음과 같습니다: • @State와 @Observable 사용 시점: @Observable 인스턴스를 생성하는 뷰만 @State를 사용합니다. 다른 뷰에서는 let으로 선언하여 사용합니다. • @Observable을 let으로 선언: 다른 뷰에서 @Observable 인스턴스를 받을 때는 let으로 선언해도 안전합니다. 인스턴스를 소유하는 뷰는 @State를 사용해야 합니다. 이 원칙을 따르면 뷰의 상태 관리와 데이터 흐름이 명확해집니다.그렇기 때문에 최소 뷰의 소유권을 가지고 있는 최상위에서는 @State 을 사용하고, 그것을 인스턴스 받어서 사용할때는 let 을 사용하게 이론적으로 안전합니다. 하지만, var 을 사용해도 error 가 발생되거나 그러진 않지만 safe code 을 위해서는 let 사용이 권장되는것입니다. @State 는 처음 instance 생성할때 viewModel 을 선언할때 사용되며 @Bindable 은 선언된 ViewModel 을 binding 하는 역활을 합니다. 자세한 사항은 iOS17 강의에서 Observation 부분을 참고하시면 됩니다. Project 에서 @Observable 을 사용해서 변환하는것도한 코드 변환 하고 확인 후에 강의및 예제 코드도 조만간 업데이트 하겠습니다.
- 0
- 2
- 140
질문&답변
2024.05.28
페이지 이동에 관해 질문이 있습니다 !
안녕하세요 oilater 님.확인이 늦어 이제 답변드리네요 죄송합니다.페이지 연결 느낌이 아니라 다른 페이지로 넘기는것은 .fullScreenCover 와 .presentationDetents 을 활용해서 sheet 의 크기와 페이지 전환을 NavigationLink 를 사용하지 않고도 구현 할 수 있습니다.자세한 사항은 링크를 참조해주세요https://sarunw.com/posts/swiftui-bottom-sheet/감사합니다예제 코드는 다음과 같습니다.import SwiftUI struct test1: View { @State private var showFullScreen = false var body: some View { VStack { Text("Home Page") .font(.largeTitle) .padding() Button(action: { showFullScreen.toggle() }) { Text("Go to Next Page") .padding() .background(Color.blue) .foregroundColor(.white) .cornerRadius(8) } // .fullScreenCover(isPresented: $showFullScreen) { // NextPageView() // FullScreenColor 와 같이 Sheet} .sheet(isPresented: $showFullScreen, content: { NextPageView() // .presentationDetents([.medium]) // 중간 사이즈 sheet // .presentationDetents([.fraction(0.7)]) // 스크린 사이즈의 70% 만 .presentationDetents([.fraction(0.3)]) // 스크린 사이즈의 30% 만 }) } } } struct NextPageView: View { @Environment(\.presentationMode) var presentationMode var body: some View { VStack { Text("Next Page") .font(.largeTitle) .padding() Button(action: { presentationMode.wrappedValue.dismiss() }) { Text("Go Back") .padding() .background(Color.red) .foregroundColor(.white) .cornerRadius(8) } } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.green) .edgesIgnoringSafeArea(.all) } } #Preview { test1() } (사진)
- 0
- 2
- 200
질문&답변
2024.05.28
Spacer() 를 넣으니 예제처럼 SafeArea 확보가 안됩니다.
안녕하세요 랑프님.확인이 늦어 이제 답변 드리네요 죄송합니다. iOS15 버전 이후로는 .background 적용시 자동으로 ignoreSafeArea 가 적용되게 xcode 에서 설정이 되었습니다. 그래서 .ignoreSafeArea(edges:[]) 를 사용하시면 위아래 색이 적용안하게 하실 수 있습니다.보다 자세한 사항은 아래 링크를 확인해 주세요감사합니다. https://developer.apple.com/documentation/swiftui/view/background(_:ignoressafeareaedges:) (사진)struct MatchedGeomatryEffectInter: View { @State private var isToggled: Bool = false @Namespace private var namespace var body: some View { VStack { if !isToggled { RoundedRectangle(cornerRadius: 20) .matchedGeometryEffect(id: "rectangle", in: namespace) .frame(width: 100, height: 100) // matchedGeometry Effect id 값과 nameSpace } // .offset(y: isToggled ? UIScreen.main.bounds.height * 0.7 : 0) Spacer() if isToggled { RoundedRectangle(cornerRadius: 20) .matchedGeometryEffect(id: "rectangle", in: namespace) .frame(width: 300, height: 100) } } //: VSTACK .frame(maxWidth: .infinity, maxHeight: .infinity) // 질문 답변 // .background(Color.green.ignoresSafeArea(edges: .bottom)) // 위에만 색적용 안되게 하기 .background(Color.green.ignoresSafeArea(edges: [])) // 모든 부위 .top, .bottom, .leading, .traling 적용안시키기 .onTapGesture { withAnimation(.spring()) { isToggled.toggle() } } } }
- 0
- 3
- 238
질문&답변
2024.05.22
Local Notification 예제 문의
안녕하세요 랑프님. 앱이 활성화될 때마다 UIApplication.shared.applicationIconBadgeNumber = 0으로 뱃지가 초기화되므로, 로컬 알림을 여러 번 발송해도 모든 알림이 뱃지 값이 1인 상태로 도착합니다. 이는 알림의 뱃지 값이 항상 초기화되기 때문에 발생합니다.이를 해결하기 위해서 UserDefaults 를 사용해서 뱃지 값을 저장하고 불러오는 방법을 사용하면 됩니다. 수정된 코드는 다음과 같습니다. *수정한 부분만 사진으로 올려드리고 전체 코드는 맨아래 있습니다.앱이 종료 되어도 뱃지값 저장하기(사진)CancelNotifiactaion 에서 값 초기화(사진)View에서 화면이 나타날때 reset 하는거 삭제(사진)수정된 코드class NotificationManager { static let instance = NotificationManager() // 인스턴스 생성 func requestAuthorization() { let option: UNAuthorizationOptions = [.alert, .sound, .badge] // UserNotification 접근 UNUserNotificationCenter.current().requestAuthorization(options: option) { (success, error) in if let error = error { print("에러: \(error)") } else { print("성공") } } } func scheduleNotification() { // UserDefaults 에다가 자장할 currentBadgeCount let currentBadgeCount = UserDefaults.standard.integer(forKey: "badgeCount") // 값을 1씩 증가 시킴 let newBadgeCount = currentBadgeCount + 1 // 증가한다음에서는 값을 저장 UserDefaults.standard.set(newBadgeCount, forKey: "badgeCount") // notification 내용 설정 let content = UNMutableNotificationContent() content.title = "Local Notification 테스트 1" content.subtitle = "앱 알람 테스트 중입니다" content.sound = .default content.badge = NSNumber(value: newBadgeCount) // 1씩 증가 시킴 // Trigger 2가지 종류 // 1.시간 기준 : Interval - 몇 초 뒤에 울릴것인지 딜레이 설정 repeats 반복 여부 설정 (최소 1분이여지 반복이 돔) let timeTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 5.0, repeats: false) // 2.날짜 기준 : DateMating 은 DateComponent 기준맞는 알림 var dateComponents = DateComponents() dateComponents.hour = 8 // hour 를 24시간 기준 dateComponents.minute = 30 dateComponents.weekday = 1 // 1은 일요일이 되고, 6은 금요일이 됨 // let calendarTigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true) // 설정한 값을 NotificationCenter 에 요청하기 let request = UNNotificationRequest( identifier: UUID().uuidString, // 각각의 request ID 값 String 을 uuid 값으로 설정 content: content, trigger: timeTrigger) UNUserNotificationCenter.current().add(request) } // 생성된 Notification Cancel 하기 func cancelNotification() { // peding notification 은 tigger 상에서 만족된 조건이 되어도 더이상 notification 되지 않게 하기 UNUserNotificationCenter.current().removeAllPendingNotificationRequests() // 아이폰 상태바를 내렸을때 남아있는 notification 없애기 UNUserNotificationCenter.current().removeAllDeliveredNotifications() // Cancel 하면 UserDefault 값 초기화 하기 UserDefaults.standard.set(0, forKey: "badgeCount") UIApplication.shared.applicationIconBadgeNumber = 0 } } struct LocalNotificationInter: View { @Environment(\.scenePhase) var scenePhase var body: some View { VStack (spacing: 40) { Button { NotificationManager.instance.requestAuthorization() } label: { Text("권한 요청하기") .font(.title2) .fontWeight(.semibold) .foregroundColor(.black) .padding() .background(Color.green) .cornerRadius(10) } Button { NotificationManager.instance.scheduleNotification() } label: { Text("Time Notification") .font(.title2) .fontWeight(.semibold) .foregroundColor(.black) .padding() .background(Color.green) .cornerRadius(10) } Button { NotificationManager.instance.scheduleNotification() } label: { Text("Calendar Notification") .font(.title2) .fontWeight(.semibold) .foregroundColor(.black) .padding() .background(Color.green) .cornerRadius(10) } Button { NotificationManager.instance.cancelNotification() } label: { Text("Notification 취소하기") .font(.title2) .fontWeight(.semibold) .foregroundColor(.black) .padding() .background(Color.green) .cornerRadius(10) } } //: VSTACK // schne 이 나타 날때 Badge 0 으로 초기화 하기 .onChange(of: scenePhase) { newValue in if newValue == .active { // 0으로 초기화 되지 않게 reset 하지 않기 // UIApplication.shared.applicationIconBadgeNumber = 0 } } } }
- 0
- 2
- 194
질문&답변
2024.05.22
Local Notification 강의 편집오류 있어요
안녕하세요 랑프님.컷편집 오류 확인하였습니다.원본파일에서 다시 수정하여 재 업로드 하겠습니다.감사합니다
- 0
- 2
- 128
질문&답변
2024.05.22
강의중 코드폴딩 단축키 (커맨트+옵션+왼쪽방향키)
안녕하세요 랑프 님.강의의 내용에 대해 혼동을 드려서 죄송합니다.단축키 부분 수정하여서 재업로드 하겠습니다.감사합니다.
- 0
- 2
- 121
질문&답변
2024.05.22
갤러리에서 슬라이더 변경시 gridSwitch 가 두번 실행됩니다.
안녕하세요 랑프님코드를 질문 주신 코드 확인하였습니다.자답 올려주신 부분 중복 호출 방지해서 해결하신 부분 알려주셔서 감사합니다.예제 코드 수정하여서 재 업로드 하겠습니다.
- 0
- 2
- 175
질문&답변
2024.05.22
scrollTransition 에서 phase 값을 찍어보고 싶습니다.
안녕하세요 랑프님.먼저 강의에서 설명이 부족한점 죄송합니다제가 확인한 결과 직접적으로 phase 를 콘솔에 print 해서 출력하는것을 여러 방법으로 시도 해봤으나 phase.value 값을 .scrollTransition 밖으로 return 해서 밖으로 빼내야 되는데 클로져가 아님에 따라 .scrollTransition 자체 API 에서 지원하지 않는거 같습니다.phase.value 의 값의 정의는 다음과 같습니다.phase.value 의 속성 범위는 -1 부터 1까지의 전환 숫자 단계를 가리킵니다.-1 : 스크롤의 위쪽이나 왼쪽에 완전히 넘어갔을 경우0 : 뷰에 완전히 표시되었을때1 : 스크롤의 아래쪽이나 오른쪽으로 완전히 넘어갔을 경우그래서 opacity 에서 넘어갈때와 나타날때 을 phase.value 값을 적용해서 스크롤시 transition 효과가 나타나게 됩니다. 더 자세한 참고는 아래 링크를 확인해 주세요 감사합니다https://farhanadji.medium.com/exploring-swiftui-scrollview-updates-from-wwdc-2023-2c69c7a813cc
- 0
- 2
- 177