[SwiftUI Bootcamp] Intermediate3

Woozoo·2023년 1월 24일
0

[SwiftUI]

목록 보기
18/26

.mask()

struct MaskBootcamp: View {
    
    @State var rating: Int = 4
    
    var body: some View {
        ZStack {
            HStack {
                ForEach(1..<6) { index in
                    Image(systemName: "star.fill")
                        .font(.largeTitle)
                        .foregroundColor(rating >= index ? Color.yellow : Color.gray)
                        .onTapGesture {
                            rating = index
                        }
                }
            }
        }
    }
}

요런 뷰가 있다고 해보자
레이팅으로 별점을 매기는 뷰임
근데 지금 tap했을 때 딱딱 끊기는 느낌이 드는데 이걸 부드럽게 이어보자

starsView를 새로 만들고, 그 위에 Rectangle을 오버레이로 올려줌
그리고 .mask(마스크할 대상)을 해주면 끝!


rating이 그려지는 뷰의 width를 알기 위해서 GeometryReader를 사용하고,
Rectangle의 frame이 rating의 값에따라 변하게 만들어줌

근데 이렇게 했을 때 문제가 발생한다

rating을 낮추는 게 안됨
overlay로 가려져서 그럼
간단히 해결하는 방법은 overlay로 가려지는 뷰가 터치 안되게 해주면 됨

그리고 rating의 값이 변경되는 부분에 withAnimation 넣어주면 끝!


Sound Effects


soundManager라는 클래스를 만들어줬음
이 클래스가 뷰 자체를 바꾸거나 값을 전달할 일이 없고,
어떤 뷰에서든 바로 접근이 가능하게 해주기 위해서 static으로 instance를 전역으로 선언해줌

AVKit을 import 하고
Sound 파일을 url로 매핑해준다!
그리고 player?.play()로 실행을 해줌


SoundManager.instance로 playSound 해주면 끝!


그리구 실행해야할 사운드가 여러개면
enum으로 case를 나누고, forResource의 이름이 enum의 rawValue가 되게 해주면 됩니다!
enum은 String을 명시해줄 경우에 case들의 rawValue는 case 이름으로 들어감


Haptics / vibrations

class HapticManager {
    static let instance = HapticManager() //Singleton
    
    func notification(type: UINotificationFeedbackGenerator.FeedbackType) {
        let generator = UINotificationFeedbackGenerator()
        generator.notificationOccurred(type)
    }
    
    func impact(style: UIImpactFeedbackGenerator.FeedbackStyle) {
        let generator = UIImpactFeedbackGenerator(style: style)
        generator.impactOccurred()
    }    
}

struct HapticsBootcamp: View {
    var body: some View {
        VStack(spacing: 20) {
            Button("success") { HapticManager.instance.notification(type: .success) }
            Button("warning") { HapticManager.instance.notification(type: .warning) }
            Button("error") { HapticManager.instance.notification(type: .error) }
            Divider()
            Button("soft") { HapticManager.instance.impact(style: .soft)}
            Button("light") { HapticManager.instance.impact(style: .light)}
            Button("medium") { HapticManager.instance.impact(style: .medium)}
            Button("rigid") { HapticManager.instance.impact(style: .rigid)}
            Button("heavy") { HapticManager.instance.impact(style: .heavy)}
        }
    }
}

type이랑 style 두개로 나눠서 만들 수 있음


Add Local Notifications

NotificationManager를 만들고 request메소드를 작성해준다!
import UserNotifications를 해줘야함
request 메소드 안의 options는 어떤 게 뜨게 할지 정해주는 거임


시뮬레이터로 실행하고 버튼을 누르면 request alert이 뜬다
허용을 하면 현재의 SUCCESS 프린트가 잘 출력되는 걸 확인할 수 있음


실제로 noti가 뜨게 해보자
3가지 정도 방법이 있는데 time, calendar, location을 이용할 수 있음

NotificationManager에서 각각 메소드로 따로 파서 만들어보자

먼저 타임을 이용하는건 위 스샷처럼 작성해주면 됨
content와 trigger 이벤트를 만들어주고,
UNUserNotificationCenter의 현재에 add!
했지만 작동을 안함...



에러 발생해서 Scene Configuration 추가해줌

근데 이거 이제 안되는 거 같다...

💡실수를 하고 있었다

local noti는 앱이 안보이는 상태에서 팝업됨!!

앱 실행하고 버튼 누르고 홈화면에서 기다리면 정상적으로 나온다!!!


뱃지는 홈화면에서 아이콘 옆에 숫자 붙어 있는 거 말하는거임
현재 구현된 대로만 하면 어플을 터치해서 들어가도 뱃지가 안 사라지고 있음

.onAppear메소드에서 처리해주자

앱을 완전히 끄고 다시 켤 때만 저 로직이 동작하는 거 같음
켜져있는 상태에선 아무리 들어가도 뱃지가 안 사라짐!
🤔 어떻게 해야 앱을 들어가기만 해도 뱃지가 사라지게 할 수 있을까?



트리거만 바꿔주면 원하는 방식으로 noti가 뜨게 해줄 수 있음
지금처럼 calendar로 설정도 가능하고

위치에 따라서도 가능함
import CoreLocation 해주고

좌표와 region을 설정하고 region에 들어올 때랑 나갈 때 어떻게할 것인지 설정해주면 끝

캔슬하는 것도 가능함

profile
우주형

0개의 댓글