widget 작업을 위해 SwiftUI를 사용할 일이 생겼을 때 이슈 하나 있어서 정리 하나 해보겠습니다. 결론부터 말하자면 VStack과 HStack 모두 기본적으로 spacing이 들어가 있습니다. 코드로 예시를 들겠습니다. struct ContentView: View { var body: some View { VStack { Text("Hello, world!") Divider() Text("글자 spacing 테스트") } } } Text, Divider와 Text 사이에 기본적으로 spacing이 애플처럼 보기 좋게 들어가 있습니다. 하지만 작업을 하다보면 자유롭게 padding을 넣어서 간격을 만들일이 생기게 됩니다. 기존 코드에 padding을 넣으면 디자인 시안과 미묘하게 다르게 됩니다. ..
UILabel 을 사용하다 보면 글자가 길어짐에 따라 라인이 추가되는데 한정된 영역에서 글자를 어떻게 처리할 지 고민하게 된다. 그러면서 lineBreakMode가 나왔고 애플에서는 가독성을 위해서 글자를 단어 단위로 잘라서 끝쪽에 애매한 부분은 다음 줄 부터 시작하게 됩니다. 일반적인 상황에서는 상관이 없지만 네이버 시리즈의 제목을 표기하는 곳같이 글자를 단어 단위로 짜르게 되면 영역이 상당히 비어 보이는 느낌을 가지게 됩니다. 그래서 문자 단위로 자르기 위해 label.lineBreakMode = .byCharWrapping 으로 변경을 하게 됩니다. 아쉽게도 .byCharWrapping 는 글자가 짤리는 영역에 … 으로 축소해주고 싶지만.. 이런식으로 끝에 넘어가도 글자가 …으로 축소 되지않습니다...
NSTextAttachment 속성을 이용해서 UILabel 앞에 이미지 붙이기 import UIKit class ViewController: UIViewController { @IBOutlet weak var testLabel: UILabel! override func viewDidLoad() { super.viewDidLoad() // 테스트할 텍스트 생성 let text = "텍스트 앞에 이미지 넣기" // NSAttributedString 으로 변경 let NStext = NSAttributedString(string: text) // attributeString 생성 let attributedString = NSMutableAttributedString(string: "") // UIImage ..
마지막 위젯을 그리는 뷰에 대해 설명하겠습니다. struct widgetWidgetEntryView : View { var entry: Provider.Entry var body: some View { Text(entry.date, style: .time) } } 일반적인 SwiftUI 에서 보여지는 뷰 입니다. @Environment(\.widgetFamily) private var family 를 선언하고 바디에서 switch famliy 를 이용하면 case 에 따른 뷰를 그릴수있습니다. struct OrdersWidgetView: View { var entry: OrdersWidget.Entry @Environment(\.widgetFamily) private var family var body:..
위젯의 핵심인 TimelineProvider에 대해 알아보겠습니다. 처음 설치했을때 샘플로 되어있는 코드입니다. struct Provider: TimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry(date: Date()) } func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { let entry = SimpleEntry(date: Date()) completion(entry) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> (..
위젯 생성되는 파일중에 Widget에 들어가면 struct widgetWidget: Widget { let kind: String = "widgetWidget" var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in widgetWidgetEntryView(entry: entry) } .configurationDisplayName("My Widget") .description("This is an example widget.") .supportedFamilies([.systemSmall,.systemMedium,.systemLarge,.accessoryCircular,.access..
번들 밑에 있는 파일에 들어가보겠습니다. import WidgetKit import SwiftUI struct Provider: TimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry(date: Date()) } func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { let entry = SimpleEntry(date: Date()) completion(entry) } func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { var..
위젯을 target을 추가하면 자신이 추가한 확장자명으로 된 폴더가 하나 만들어지게 됩니다. 먼저 bundle로 가보겠습니다. import WidgetKit import SwiftUI @main struct widgetWidgetBundle: WidgetBundle { var body: some Widget { widgetWidget() } } 와 같은 형식으로 되어있고 번들에는 앞으로 만들 위젯에 대한 구조체를 선언해서 놓으면 됩니다. 애플에서 제공하는 FoodTruck 샘플을 보면 아래와 같이 사용하고 있습니다. import WidgetKit import SwiftUI @main struct Widgets: WidgetBundle { var body: some Widget { // MARK: - Li..