SwiftUI: Difference between revisions

From Chorke Wiki
Jump to navigation Jump to search
 
(30 intermediate revisions by the same user not shown)
Line 23: Line 23:
     static var previews: some View {
     static var previews: some View {
         ContentView()
         ContentView()
    }
}
</source>
==ContextMenu==
<source lang="swift">
Text("Rails").contextMenu {
    Button(action: {}){
        Text("LRT")
        Image(systemName: "globe")
    }
    Button(action: {}){
        Text("MRT")
        Image(systemName: "location.circle")
     }
     }
}
}
Line 72: Line 86:
     @State var date:Date = .init()
     @State var date:Date = .init()
     let gregorian: Calendar = .init(identifier: .gregorian)
     let gregorian: Calendar = .init(identifier: .gregorian)
     let primary  : UIColor = ThemeColor.midnightBlue.uicolor
     let secondary: UIColor = .parse(0xE0B355)
     let secondary: UIColor = ThemeColor.sharpOrange.uicolor
     let tersiary : UIColor = .parse(0xE7EEEF)
     let tersiary : UIColor = ThemeColor.whitishBlue.uicolor
     let primary  : UIColor = .parse(0x346C7C)
      
      
     public func makeUIView(context: Context) -> CalendarView {
     public func makeUIView(context: Context) -> CalendarView {
Line 168: Line 182:


class MyFSCalendarController: UIViewController, FSCalendarDelegateAppearance {
class MyFSCalendarController: UIViewController, FSCalendarDelegateAppearance {
     let secondary: UIColor = ThemeColor.sharpOrange.uicolor
     let secondary: UIColor = .parse(0xE0B355)
     let primary: UIColor = ThemeColor.midnightBlue.uicolor
     let tersiary : UIColor = .parse(0xE7EEEF)
     let tersiary: UIColor = ThemeColor.whitishBlue.uicolor
     let primary  : UIColor = .parse(0x346C7C)
      
      
     fileprivate let formatter: DateFormatter = {
     fileprivate let formatter: DateFormatter = {
Line 181: Line 195:
      
      
     override func loadView() {
     override func loadView() {
         let width: CGFloat = ThemeSettings.width - 40
         let width: CGFloat = UIScreen.main.bounds.width - 40
         let frame: CGRect  = .init(x: 0, y: 0, width: width, height: 300)
         let frame: CGRect  = .init(x: 0, y: 0, width: width, height: 300)
         let view:  UIView  = .init(frame: frame)
         let view:  UIView  = .init(frame: frame)
Line 249: Line 263:
}
}
</source>
</source>
==Singleton==
<source lang="swift">
class NetworkManager {
    let baseURL: URL
    private init(baseURL: URL) {
        self.baseURL = baseURL
    }
    // MARK: - sharedNetworkManager
    private static var sharedNetworkManager: NetworkManager = {
        let networkManager = NetworkManager(baseURL: API.baseURL)
        return networkManager
    }()
    // MARK: - shared
    class func shared() -> NetworkManager {
        return Self.sharedNetworkManager
    }
}
</source>
==State Variable==
<source lang="swift">
import SwiftUI
struct StateInitView: View {
    @State var isBusy: Bool = false
    var title: String
   
    init(_ title: String,_ isBusy: Bool = false) {
        self._isBusy = State(initialValue: isBusy)
        self.title = title
    }
    var body: some View {
        ZStack {
            if (self.isBusy){
                Text("Baking your cake!")
            } else {
                Text("Collect your cake.")
            }
        }
    }
}
</source>
==Binding Variable==
<source lang="swift">
struct MyCheckGroup: View {
    @Binding var group : [ResourceLabel]
    var action: ((ResourceLabel) -> Void)? = nil
   
    var body: some View {
        HStack(alignment: .top, spacing: 20) {
            ForEach(Array(self.group.enumerated()), id: \.offset) { index, model in
                MyCheckBox(model: .constant(model), action: self.action)
            }
        }
    }
}
struct MyCheckBox: View {
    @Binding var model: ResourceLabel
    var action: ((ResourceLabel) -> Void)? = nil
   
    var body: some View {
        //TODO
    }
}
</source>
==For Each==
{|
| valign="top" |
'''Id:'''
<source lang="swift">
ForEach(self.labels, id: \.id) { label in
    AccordionItem(label: label){ label in
        self.addAccordionView(label)
    }
}
</source>
| valign="top" |
'''Offset:'''
<source lang="swift">
ForEach(Array(self.labels.enumerated()), id: \.offset) { index, label in
    AccordionItem(label: label){ label in
        self.addAccordionView(label)
    }
}
</source>
|}


==References==
==References==
Line 353: Line 462:


| valign="top" |
| valign="top" |
* [https://www.hackingwithswift.com/example-code/system/how-to-run-code-after-a-delay-using-asyncafter-and-perform After Delay <code>asyncAfter()</code> and <code>perform()</code>]
* [https://medium.com/swift2go/writing-cleaner-asynchronous-code-in-swift-using-promise-pattern-f608254a349c Cleaner Asynchronous Code Using Promise]
* [https://stackoverflow.com/questions/56505043 Dynamic View width of another View]
* [https://stackoverflow.com/questions/56505043 Dynamic View width of another View]
* [https://stackoverflow.com/questions/57681885 Get Current Location using SwiftUI]
* [https://stackoverflow.com/questions/57681885 Get Current Location using SwiftUI]
* [https://stackoverflow.com/questions/57305372 Picker Selection by using Tag]
* [https://cocoacasts.com/what-is-a-singleton-and-how-to-create-one-in-swift Singleton Object In Swift]
* [https://fuckingswiftui.com/ Postmortem of SwiftUI]
* [https://www.thetopsites.net/article/52447981.shtml Padding a Swift String]
* [https://www.thetopsites.net/article/52447981.shtml Padding a Swift String]
* [https://fuckingswiftui.com/ Fucking SwiftUI]
* [https://theswiftdev.com/promises-in-swift-for-beginners/ Promises in Swift]
* [https://zonneveld.dev/swiftui-form/ SwiftUI Form]
|}
-----
{|
| valign="top" |
* [https://stackoverflow.com/questions/44575293 JSONDecoder use a default value instead of Optional]
* [https://stackoverflow.com/questions/56658558 Bind a grid of buttons of same width and height]
* [https://swiftui-lab.com/communicating-with-the-view-tree-part-1/ Inspecting the View Tree by PreferenceKey]
* [https://www.hackingwithswift.com/books/ios-swiftui/triggering-events-repeatedly-using-a-timer Triggering events repeatedly using a Timer]
* [https://stackoverflow.com/questions/57134259 Deprecation of <code>keyWindow</code> in iOS 13.0]
* [https://stackoverflow.com/questions/56505043 Bind the view the size of another view]
* [https://swiftui-lab.com/geometryreader-to-the-rescue/ GeometryReader to the Rescue]
* [https://stackoverflow.com/questions/56997725 Same Width Views in List Rows]
* [https://stackoverflow.com/questions/56474019 How to change ListStyle in List]
* [https://stackoverflow.com/questions/56685964 SwiftUI <code>@Binding</code> Initialise]
 
| valign="top" |
* [https://stackoverflow.com/questions/59404039/ Play audio using AVAudioPlayer in SwiftUI]
* [https://medium.com/@mattoakes/a-better-way-to-automatically-merge-changes-in-your-xcode-project-files-3d83b3583fe4 Automatically Merge XCode Project]
* [https://stackoverflow.com/questions/25736470/ Play sound when press a button]
* [https://stackoverflow.com/questions/57153729/ Audio not playing in SwiftUI]
* [https://medium.com/macoclock/how-to-use-webkit-webview-in-swiftui-4b944d04190a WebKit WebView in SwiftUI]
* [https://stackoverflow.com/questions/34563329/how-to-play-mp3-audio-from-url-in-ios-swift/50991478 Play MP3 Audio from URL]


|}
|}

Latest revision as of 21:38, 30 September 2020

ContentView

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            HStack {
                Text("Joshua Tree National Park")
                    .font(.subheadline)
                Spacer()
                Text("California")
                    .font(.subheadline)
            }
        }
        .padding()
    }
}

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

ContextMenu

Text("Rails").contextMenu {
    Button(action: {}){
        Text("LRT")
        Image(systemName: "globe")
    }
    Button(action: {}){
        Text("MRT")
        Image(systemName: "location.circle")
    }
}

MyPDFView

// MARK: - MyPDFView
fileprivate struct MyPDFView: UIViewRepresentable {
    @Binding var data: Data

    func makeUIView(context: UIViewRepresentableContext<MyPDFView>) -> UIView {
        let empty = UIView()
      //guard let provider = CGDataProvider(data: self.data as CFData) else {return empty}
      //guard let document = CGPDFDocument(provider) else {return empty}
        guard let url = URL(string: "https://api.chorke.org/academia/api/v1.0/health/card/01890600.pdf") else {return empty}
        guard let document = CGPDFDocument(url as CFURL) else {return empty}
        guard let page     = document.page(at: 1) else {return empty}
        let pageRect = page.getBoxRect(.mediaBox)
        let renderer = UIGraphicsImageRenderer(size: pageRect.size)
        let uiImage  = renderer.image { ctx in
            UIColor.white.set()
            ctx.fill(pageRect)
            ctx.cgContext.translateBy(x: 0.0, y: pageRect.size.height)
            ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
            ctx.cgContext.drawPDFPage(page)
        }
        let view = UIImageView(image: uiImage)
        view.contentMode = .scaleAspectFill
        return view
    }

    func updateUIView(_ view: UIView, context: UIViewRepresentableContext<MyPDFView>) {
        // MARK: - TODO
    }
}

MyKDCalendar

MyKDCalendar().frame(minWidth: 200, minHeight: 350).background(ThemeColor.midnightBlue.color.opacity(0.5)).padding(.bottom, 20)
import SwiftUI
import KDCalendar

public struct MyKDCalendar: UIViewRepresentable {
    @State var date:Date = .init()
    let gregorian: Calendar = .init(identifier: .gregorian)
    let secondary: UIColor = .parse(0xE0B355)
    let tersiary : UIColor = .parse(0xE7EEEF)
    let primary  : UIColor = .parse(0x346C7C)
    
    public func makeUIView(context: Context) -> CalendarView {
        let style = self.getStyle(self.primary, self.secondary, self.tersiary)
        let calendar: CalendarView = .init()
        calendar.direction = .horizontal
        calendar.marksWeekends = true
        calendar.style = style
        
        calendar.setDisplayDate(date, animated: true)
        calendar.selectDate(date)
        calendar.dataSource = self
        calendar.delegate = self
        return calendar
    }
    
    public func updateUIView(_ calendar: CalendarView, context: Context) {
        calendar.selectDate(date)
    }
}

extension MyKDCalendar: CalendarViewDataSource {
    public func startDate() -> Date {
        return Date.init()
    }
    
    public func endDate() -> Date {
        return self.gregorian.date(byAdding: .month, value: 3, to: Date.init())!
    }
    
    public func headerString(_ date: Date) -> String? {
        return nil
    }
    
    private func getStyle(_ primary: UIColor, _ secondary: UIColor, _ tersiary: UIColor) -> CalendarView.Style {
        let style: CalendarView.Style = .init()
        style.cellSelectedBorderColor = secondary
        style.cellSelectedTextColor = tersiary
        style.cellSelectedColor = secondary
        style.firstWeekday = .sunday
        
        style.weekdaysBackgroundColor = primary
        style.headerBackgroundColor = primary
        style.weekdaysTextColor = tersiary
        style.headerTextColor = tersiary
        
        style.cellTextColorWeekend = secondary
        style.cellTextColorDefault = primary
        style.cellTextColorToday = tersiary
        
        style.cellColorOutOfRange = .systemGray
        style.cellColorDefault = tersiary
        style.cellColorToday = primary
        return style
    }
}

extension MyKDCalendar: CalendarViewDelegate {
    public func calendar(_ calendar: CalendarView, didDeselectDate date: Date) {}
    public func calendar(_ calendar: CalendarView, didScrollToMonth date: Date) {}
    public func calendar(_ calendar: CalendarView, didSelectDate date: Date, withEvents events: [CalendarEvent]) {}
    public func calendar(_ calendar: CalendarView, didLongPressDate date: Date, withEvents events: [CalendarEvent]?) {}
    public func calendar(_ calendar: CalendarView, canSelectDate date: Date) -> Bool {
        return true
    }
}

MyFSCalendar

MyFSCalendar().frame(minWidth: 200, minHeight: 320).padding(.leading, 5)
import SwiftUI
import FSCalendar

struct MyFSCalendar: UIViewControllerRepresentable {
    func makeUIViewController(context: UIViewControllerRepresentableContext<MyFSCalendar>) -> MyFSCalendarController {
        let calendar: MyFSCalendarController = .init()
        return calendar
    }

    func updateUIViewController(_ calendar: MyFSCalendarController, context: UIViewControllerRepresentableContext<MyFSCalendar>) {
        // MARK: - TODO
    }
}
import UIKit
import FSCalendar

class MyFSCalendarController: UIViewController, FSCalendarDelegateAppearance {
    let secondary: UIColor = .parse(0xE0B355)
    let tersiary : UIColor = .parse(0xE7EEEF)
    let primary  : UIColor = .parse(0x346C7C)
    
    fileprivate let formatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
    
    fileprivate weak var calendar: FSCalendar!
    
    override func loadView() {
        let width: CGFloat = UIScreen.main.bounds.width - 40
        let frame: CGRect  = .init(x: 0, y: 0, width: width, height: 300)
        let view:  UIView  = .init(frame: frame)
        self.view = view
        
        let calendar: FSCalendar = .init(frame: frame)
        calendar.allowsMultipleSelection = false
        calendar.dataSource = self
        calendar.delegate = self
        
        view.addSubview(calendar)
        self.calendar = calendar
        
        calendar.calendarHeaderView.backgroundColor = self.primary
        calendar.calendarWeekdayView.backgroundColor = self.primary
        calendar.appearance.headerTitleColor = self.tersiary
        calendar.appearance.weekdayTextColor = self.tersiary
        
        calendar.appearance.eventSelectionColor = self.tersiary
        calendar.appearance.eventDefaultColor = self.primary
        calendar.appearance.eventOffset = CGPoint(x: 0, y: -7)
        
        calendar.appearance.todaySelectionColor = self.primary
        calendar.appearance.selectionColor = self.secondary
        calendar.appearance.todayColor = self.primary
        
        calendar.appearance.titleWeekendColor = self.secondary
        calendar.appearance.titleDefaultColor = self.primary

        calendar.swipeToChooseGesture.isEnabled = true
        let scopeGesture = UIPanGestureRecognizer(target: calendar, action: #selector(calendar.handleScopeGesture(_:)));
        scopeGesture.delegate = self
        calendar.addGestureRecognizer(scopeGesture)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.calendar.scope = .month
        self.calendar.select(Date.init())
        self.calendar.accessibilityIdentifier = "calendar"
    }
}

extension MyFSCalendarController: FSCalendarDataSource {
    func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
        debugPrint("did select date \(self.formatter.string(from: date))")
        let selectedDates = calendar.selectedDates.map({self.formatter.string(from: $0)})
        debugPrint("selected dates is \(selectedDates)")
        if monthPosition == .next || monthPosition == .previous {
            calendar.setCurrentPage(date, animated: true)
        }
    }
}

extension MyFSCalendarController: FSCalendarDelegate {
    func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) {
        self.calendar.frame.size.height = bounds.height
        self.view.layoutIfNeeded()
    }
}

extension MyFSCalendarController: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        debugPrint("UIGestureRecognizer")
        return true
    }
}

Singleton

class NetworkManager {
    let baseURL: URL

    private init(baseURL: URL) {
        self.baseURL = baseURL
    }

    // MARK: - sharedNetworkManager
    private static var sharedNetworkManager: NetworkManager = {
        let networkManager = NetworkManager(baseURL: API.baseURL)
        return networkManager
    }()

    // MARK: - shared
    class func shared() -> NetworkManager {
        return Self.sharedNetworkManager
    }
}

State Variable

import SwiftUI

struct StateInitView: View {
    @State var isBusy: Bool = false
    var title: String
    
    init(_ title: String,_ isBusy: Bool = false) {
        self._isBusy = State(initialValue: isBusy)
        self.title = title
    }

    var body: some View {
        ZStack {
            if (self.isBusy){
                Text("Baking your cake!")
            } else {
                Text("Collect your cake.")
            }
        }
    }
}

Binding Variable

struct MyCheckGroup: View {
    @Binding var group : [ResourceLabel]
    var action: ((ResourceLabel) -> Void)? = nil
    
    var body: some View {
        HStack(alignment: .top, spacing: 20) {
            ForEach(Array(self.group.enumerated()), id: \.offset) { index, model in
                MyCheckBox(model: .constant(model), action: self.action)
            }
        }
    }
}

struct MyCheckBox: View {
    @Binding var model: ResourceLabel
    var action: ((ResourceLabel) -> Void)? = nil
    
    var body: some View {
        //TODO
    }
}

For Each

Id:

ForEach(self.labels, id: \.id) { label in
    AccordionItem(label: label){ label in
        self.addAccordionView(label)
    }
}

Offset:

ForEach(Array(self.labels.enumerated()), id: \.offset) { index, label in
    AccordionItem(label: label){ label in
        self.addAccordionView(label)
    }
}

References