1月

1/1~

アプリ開発

二つのアプリの9割が完成したので(簡単な仕上げを残して)、コードを以下に記す。デザインや詳細機能は発表で紹介する。

DesignGo

  1. // DesignGoApp
  2. import SwiftUI
  3. @main
  4. struct DesignGoApp: App {
  5.     let persistenceController = PersistenceController.shared
  6.     var body: some Scene {
  7.         WindowGroup {
  8.             ContentView()
  9.                 .environment(\.managedObjectContext, persistenceController.container.viewContext)
  10.         }
  11.     }
  12. }
  13. // ContentView
  14. import SwiftUI
  15. import CoreData
  16. struct ContentView: View {
  17.     
  18.     @Environment(\.managedObjectContext) private var viewContext
  19.     
  20.     @State var showingSheet = false
  21.     
  22.     @FetchRequest(sortDescriptors: [])
  23.     private var todos: FetchedResults<Todo>
  24.     
  25.     @FetchRequest(sortDescriptors: [])
  26.     private var wants: FetchedResults<Want>
  27.     
  28.     @FetchRequest(sortDescriptors: [])
  29.     private var moves: FetchedResults<Move>
  30.     
  31.     @FetchRequest(sortDescriptors: [])
  32.     private var belongings: FetchedResults<Belonging>
  33.     
  34.     @FetchRequest(sortDescriptors: [])
  35.     private var memos: FetchedResults<Memo>
  36.     
  37.     @State var randomInt = 0
  38.     
  39.     @State var showAnimation = false
  40.     
  41.     var body: some View {
  42.         ZStack {
  43.             Color(red: 0.97, green: 0.97, blue: 0.95).edgesIgnoringSafeArea(.all)
  44.             if todos.count == 0 && wants.count == 0 && moves.count == 0 && belongings.count == 0 && memos.count == 0 {
  45.                 Text("Design your life !").font(.largeTitle)
  46.             }
  47.             ScrollView {
  48.                 VStack(alignment: .leading, spacing: 20) {
  49.                     Group {
  50.                         if todos.count != 0 {
  51.                             Text("todos(\(todos.count))")
  52.                                 .fontWeight(.medium)
  53.                                 .offset(x: 10, y: 10)
  54.                                 .font(.title)
  55.                         }
  56.                         
  57.                         ScrollView(.horizontal, showsIndicators: false){
  58.                             HStack {
  59.                                 ForEach(todos){ todo in
  60.                                     todoFrame(todoItem: todo)
  61.                                         .padding()
  62.                                         .contextMenu {
  63.                                             Button(action:{
  64.                                                     withAnimation{
  65.                                                         viewContext.delete(todo)
  66.                                                         self.randomInt = Int.random(in: 0..<2)
  67.                                                         try! viewContext.save()
  68.                                                     }
  69.                                             }, label: {
  70.                                                 Text("Done")})
  71.                                             Button(action: {
  72.                                                     withAnimation {
  73.                                                         viewContext.delete(todo)
  74.                                                         try! viewContext.save()
  75.                                                     }
  76.                                             }, label: {
  77.                                                     Text("Delete")})
  78.                                         }
  79.                                 }
  80.                             }
  81.                         }.offset(x: 2)
  82.                     }
  83.                     Group {
  84.                         if wants.count != 0 {
  85.                             Text("wants(\(wants.count))")
  86.                                 .fontWeight(.medium)
  87.                                 .offset(x: 10, y: 10)
  88.                                 .font(.title)
  89.                         }
  90.                       
  91.                         ScrollView(.horizontal, showsIndicators: false){
  92.                             HStack {
  93.                                 ForEach(wants){ want in
  94.                                     wantFrame(wantItem: want)
  95.                                         .padding()
  96.                                         .contextMenu {
  97.                                             Button(action:{
  98.                                                     withAnimation{
  99.                                                         viewContext.delete(want)
  100.                                                         self.randomInt = Int.random(in: 0..<2)
  101.                                                         try! viewContext.save()
  102.                                                     }
  103.                                             }, label: {
  104.                                                     Text("Done")})
  105.                                             Button(action: {
  106.                                                     withAnimation {
  107.                                                         viewContext.delete(want)
  108.                                                         try! viewContext.save()
  109.                                                     }
  110.                                             }, label: {
  111.                                                     Text("Delete")})
  112.                                         }
  113.                                 }
  114.                             }
  115.                         }.offset(x: 2)
  116.                     }
  117.                     Group {
  118.                         if moves.count != 0 {
  119.                             Text("moves(\(moves.count))")
  120.                                 .fontWeight(.medium)
  121.                                 .offset(x: 10, y: 10)
  122.                                 .font(.title)
  123.                         }
  124.                         ScrollView(.horizontal, showsIndicators: false){
  125.                             HStack {
  126.                                 ForEach(moves){ move in
  127.                                     moveFrame(moveItem: move)
  128.                                         .padding()
  129.                                         .contextMenu {
  130.                                             Button(action:{
  131.                                                     withAnimation{
  132.                                                         viewContext.delete(move)
  133.                                                         self.randomInt = Int.random(in: 0..<2)
  134.                                                         try! viewContext.save()
  135.                                                     }
  136.                                             }, label: {
  137.                                                     Text("Done")})
  138.                                             Button(action: {
  139.                                                     withAnimation {
  140.                                                         viewContext.delete(move)
  141.                                                         try! viewContext.save()
  142.                                                     }
  143.                                             }, label: {
  144.                                                     Text("Delete")})
  145.                                         }
  146.                                 }
  147.                             }
  148.                         }.offset(x: 2)
  149.                     }
  150.                     Group {
  151.                         if belongings.count != 0 {
  152.                             Text("belongings(\(belongings.count))")
  153.                                 .fontWeight(.medium)
  154.                                 .offset(x: 10, y: 10)
  155.                                 .font(.title)
  156.                         }
  157.                         ScrollView(.horizontal, showsIndicators: false){
  158.                             HStack {
  159.                                 ForEach(belongings){ belonging in
  160.                                     belongingFrame(belongingItem: belonging)
  161.                                         .padding()
  162.                                         .contextMenu {
  163.                                             Button(action:{
  164.                                                     withAnimation{
  165.                                                         viewContext.delete(belonging)
  166.                                                         self.randomInt = Int.random(in: 0..<2)
  167.                                                         try! viewContext.save()
  168.                                                     }
  169.                                             }, label: {
  170.                                                     Text("Done")})
  171.                                             Button(action: {
  172.                                                     withAnimation {
  173.                                                         viewContext.delete(belonging)
  174.                                                         try! viewContext.save()
  175.                                                     }
  176.                                             }, label: {
  177.                                                     Text("Delete")})
  178.                                         }
  179.                                 }
  180.                             }
  181.                         }.offset(x: 2)
  182.                     }
  183.                     Group {
  184.                         if memos.count != 0 {
  185.                             Text("memos(\(memos.count))")
  186.                                 .fontWeight(.medium)
  187.                                 .offset(x: 10, y: 10)
  188.                                 .font(.title)
  189.                         }
  190.                         ScrollView(.horizontal, showsIndicators: false){
  191.                             HStack {
  192.                                 ForEach(memos){ memo in
  193.                                     memoFrame(memoItem: memo)
  194.                                         .padding()
  195.                                         .contextMenu {
  196.                                             Button(action:{
  197.                                                     withAnimation{
  198.                                                         viewContext.delete(memo)
  199.                                                         self.randomInt = Int.random(in: 0..<2)
  200.                                                         try! viewContext.save()
  201.                                                     }
  202.                                             }, label: {
  203.                                                     Text("Done")})
  204.                                             Button(action: {
  205.                                                     withAnimation {
  206.                                                         viewContext.delete(memo)
  207.                                                         try! viewContext.save()
  208.                                                     }
  209.                                             }, label: {
  210.                                                     Text("Delete")})
  211.                                         }
  212.                                 }
  213.                             }
  214.                         }.offset(x: 2)
  215.                     }
  216.                 }
  217.             }.sheet(isPresented: $showingSheet) {
  218.                 settingSheet()
  219.             }
  220.             GeometryReader { geometry in
  221.                 Button(action: {self.showingSheet.toggle()}){
  222.                     Circle()
  223.                     .fill(buttonColor)
  224.                     .frame(width: 60, height: 60)
  225.                     .shadow(radius: 10, x: 5, y: 5)
  226.             }.position(x:geometry.frame(in: .global).maxX-50 , y:geometry.frame(in: .global).maxY-70)
  227.             }
  228.             if randomInt == 1 {
  229.                 withAnimation {
  230.                     Animation().edgesIgnoringSafeArea(.all)
  231.                         .gesture(
  232.                             TapGesture()
  233.                                 .onEnded { _ in
  234.                                     self.randomInt = 0
  235.                                 }
  236.                                 )
  237.                 }
  238.             }
  239.         }
  240.     }
  241. }
  242. fileprivate let gradientColors = Gradient(colors: [.yellow, .white, .orange])
  243. fileprivate let buttonColor = AngularGradient(gradient: gradientColors, center: .center)
  244. // Animation
  245. import SwiftUI
  246. struct Animation: View {
  247.     var body: some View {
  248.         ZStack {
  249.             Color(red: 0, green: 0, blue: 0, opacity: 0.8)
  250.             LottieView()
  251.         }
  252.     }
  253. }
  254. // LottieView
  255. import SwiftUI
  256. import Lottie
  257. struct LottieView: UIViewRepresentable {
  258.     
  259.     typealias UIViewType = UIView
  260.     
  261.     var name = "fireworks"
  262.     
  263.     func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
  264.         let view = AnimationView(name: name, bundle: Bundle.main)
  265.         view.play()
  266.         return view
  267.     }
  268.     
  269.     func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
  270.     }
  271. }
  272. // settingSheet
  273. import SwiftUI
  274. struct settingSheet: View {
  275.     
  276.     @Environment(\.managedObjectContext) private var viewContext
  277.     @Environment (\.presentationMode) var presentationMode
  278.     
  279.     let categories = ["Todo","Want","Move","Belonging","Memo"]
  280.     @State var categoryIndex = 0
  281.     
  282.     @FetchRequest(sortDescriptors: [])
  283.     private var todos: FetchedResults<Todo>
  284.     @State var todo = ""
  285.     @State var place = ""
  286.     @State var start = Date()
  287.     @State var end = Date()
  288.     @State var todoCategoryIndex = 0
  289.     @State var cost = ""
  290.     let todoCategories = ["","study","work","shopping"]
  291.     
  292.     @FetchRequest(sortDescriptors: [])
  293.     private var wants: FetchedResults<Want>
  294.     @State var want = ""
  295.     @State var place2 = ""
  296.     @State var start2 = Date()
  297.     @State var end2 = Date()
  298.     @State var wantCategoryIndex = 0
  299.     @State var cost2 = ""
  300.     let wantCategories = ["","study","work","shopping"]
  301.     
  302.     @FetchRequest(sortDescriptors: [])
  303.     private var moves: FetchedResults<Move>
  304.     @State var howManyTransfer = 0
  305.     @State var station = ""
  306.     @State var line = ""
  307.     @State var time = Date()
  308.     
  309.     @State var station2 = ""
  310.     @State var line2 = ""
  311.     @State var time2 = Date()
  312.     @State var station3 = ""
  313.     @State var line3 = ""
  314.     @State var time3 = Date()
  315.     @State var station4 = ""
  316.     @State var line4 = ""
  317.     @State var time4 = Date()
  318.     @State var station5 = ""
  319.     @State var line5 = ""
  320.     @State var time5 = Date()
  321.     @State var station6 = ""
  322.     @State var line6 = ""
  323.     @State var time6 = Date()
  324.     @State var station7 = ""
  325.     @State var time7 = Date()
  326.     
  327.     @FetchRequest(sortDescriptors: [])
  328.     private var belongings: FetchedResults<Belonging>
  329.     @State var belonging = ""
  330.     
  331.     @FetchRequest(sortDescriptors: [])
  332.     private var memos: FetchedResults<Memo>
  333.     @State var memo = ""
  334.     
  335.     var body: some View {
  336.         
  337.         VStack(){
  338.             Picker(selection: $categoryIndex, label: Text("choose a category")) {
  339.                 ForEach(0 ..< categories.count) {
  340.                     Text(self.categories[$0]).tag($0)
  341.                     }
  342.             }
  343.             if self.categoryIndex == 0 {
  344.                 Form {
  345.                     Section(header: Text("todo deatils")) {
  346.                         TextField("Please enter todo", text: $todo)
  347.                         TextField("Please enter place", text: $place)
  348.                         TextField("How much does it cost?", text: $cost).keyboardType(.numberPad)
  349.                         Picker(selection: $todoCategoryIndex, label: Text("category")) { ForEach(0 ..< todoCategories.count) {
  350.                             Text(self.todoCategories[$0]).tag($0)
  351.                             }
  352.                         }.pickerStyle(WheelPickerStyle())
  353.                         DatePicker("from",selection: $start)
  354.                         DatePicker("to",selection: $end)
  355.                     }
  356.                     Button(action: {
  357.                         let newTodo = Todo (context: viewContext)
  358.                         newTodo.todo = self.todo
  359.                         newTodo.category = self.categories[self.categoryIndex]
  360.                         newTodo.place = self.place
  361.                         newTodo.id = UUID()
  362.                         newTodo.start = self.start
  363.                         newTodo.end = self.end
  364.                         newTodo.cost = self.cost
  365.                         
  366.                         do {
  367.                            try viewContext.save()
  368.                             presentationMode.wrappedValue.dismiss()
  369.                         } catch {
  370.                             let error = error as NSError
  371.                             fatalError("Unresolved Error: \(error)")
  372.                           }
  373.                         }, label: {
  374.                         Text("Save")
  375.                     })
  376.                 }
  377.             }
  378.             else if self.categoryIndex == 1 {
  379.                 Form {
  380.                     Section(header: Text("want deatils")) {
  381.                         TextField("Please enter want", text: $want)
  382.                         TextField("Please enter place", text: $place2)
  383.                         TextField("How much does it cost?", text: $cost2).keyboardType(.numberPad)
  384.                         Picker(selection: $wantCategoryIndex, label: Text("category")) { ForEach(0 ..< wantCategories.count) {
  385.                             Text(self.wantCategories[$0]).tag($0)
  386.                             }
  387.                         }.pickerStyle(WheelPickerStyle())
  388.                         DatePicker("from",selection: $start2)
  389.                         DatePicker("to",selection: $end2)
  390.                     }
  391.                     Button(action: {
  392.                         let newWant = Want (context: viewContext)
  393.                         newWant.want = self.want
  394.                         newWant.category2 = self.categories[self.categoryIndex]
  395.                         newWant.place2 = self.place
  396.                         newWant.id = UUID()
  397.                         newWant.start2 = self.start2
  398.                         newWant.end2 = self.end2
  399.                         newWant.cost2 = self.cost2
  400.                         
  401.                         do {
  402.                            try viewContext.save()
  403.                             presentationMode.wrappedValue.dismiss()
  404.                         } catch {
  405.                             let error = error as NSError
  406.                             fatalError("Unresolved Error: \(error)")
  407.                           }
  408.                         }, label: {
  409.                         Text("Save")
  410.                     })
  411.                 }
  412.             }
  413.             else if self.categoryIndex == 2 {
  414.                 VStack {
  415.                         Form {
  416.                             Section(header: Text("how many transfers ?")) {
  417.                                 Stepper(value: $howManyTransfer ,in: 0...4) {
  418.                                     Text(" \(howManyTransfer) \(howManyTransfer == 0 ? "transfer" : "transfers")").padding()
  419.                                 }
  420.                             }
  421.                             Section(header: Text("Departure")) {
  422.                                 TextField("Please enter station name", text: $station)
  423.                                 TextField("Please enter line name", text: $line)
  424.                                 DatePicker("Departing at",selection: $time, displayedComponents: .hourAndMinute)
  425.                             }
  426.                             if howManyTransfer == 1 {
  427.                                 Section(header: Text("Transfer")) {
  428.                                     TextField("Please enter station name", text: $station2)
  429.                                     TextField("Please enter line name", text: $line2)
  430.                                     DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
  431.                                 }
  432.                             }
  433.                             else if howManyTransfer == 2 {
  434.                                 Section(header: Text("Transfer")) {
  435.                                     TextField("Please enter station name", text: $station2)
  436.                                     TextField("Please enter line name", text: $line2)
  437.                                     DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
  438.                                 }
  439.                                 Section(header: Text("Transfer")) {
  440.                                     TextField("Please enter station name", text: $station3)
  441.                                     TextField("Please enter line name", text: $line3)
  442.                                     DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
  443.                                 }
  444.                             }
  445.                             else if howManyTransfer == 3 {
  446.                                 Section(header: Text("Transfer")) {
  447.                                     TextField("Please enter station name", text: $station2)
  448.                                     TextField("Please enter line name", text: $line2)
  449.                                     DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
  450.                                 }
  451.                                 Section(header: Text("Transfer")) {
  452.                                     TextField("Please enter station name", text: $station3)
  453.                                     TextField("Please enter line name", text: $line3)
  454.                                     DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
  455.                                 }
  456.                                 Section(header: Text("Transfer")) {
  457.                                     TextField("Please enter station name", text: $station4)
  458.                                     TextField("Please enter line name", text: $line4)
  459.                                     DatePicker("Departure",selection: $time4, displayedComponents: .hourAndMinute)
  460.                                 }
  461.                             }
  462.                             else if howManyTransfer == 4 {
  463.                                 Section(header: Text("Transfer")) {
  464.                                     TextField("Please enter station name", text: $station2)
  465.                                     TextField("Please enter line name", text: $line2)
  466.                                     DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
  467.                                 }
  468.                                 Section(header: Text("Transfer")) {
  469.                                     TextField("Please enter station name", text: $station3)
  470.                                     TextField("Please enter line name", text: $line3)
  471.                                     DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
  472.                                 }
  473.                                 Section(header: Text("Transfer")) {
  474.                                     TextField("Please enter station name", text: $station4)
  475.                                     TextField("Please enter line name", text: $line4)
  476.                                     DatePicker("Departure",selection: $time4, displayedComponents: .hourAndMinute)
  477.                                 }
  478.                                 Section(header: Text("Transfer")) {
  479.                                     TextField("Please enter station name", text: $station5)
  480.                                     TextField("Please enter line name", text: $line5)
  481.                                     DatePicker("Departure",selection: $time5, displayedComponents: .hourAndMinute)
  482.                                 }
  483.                             }
  484.                             else if howManyTransfer == 5 {
  485.                                 Section(header: Text("Transfer")) {
  486.                                     TextField("Please enter station name", text: $station2)
  487.                                     TextField("Please enter line name", text: $line2)
  488.                                     DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
  489.                                 }
  490.                                 Section(header: Text("Transfer")) {
  491.                                     TextField("Please enter station name", text: $station3)
  492.                                     TextField("Please enter line name", text: $line3)
  493.                                     DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
  494.                                 }
  495.                                 Section(header: Text("Transfer")) {
  496.                                     TextField("Please enter station name", text: $station4)
  497.                                     TextField("Please enter line name", text: $line4)
  498.                                     DatePicker("Departure",selection: $time4, displayedComponents: .hourAndMinute)
  499.                                 }
  500.                                 Section(header: Text("Transfer")) {
  501.                                     TextField("Please enter station name", text: $station5)
  502.                                     TextField("Please enter line name", text: $line5)
  503.                                     DatePicker("Departure",selection: $time5, displayedComponents: .hourAndMinute)
  504.                                 }
  505.                                 Section(header: Text("Transfer")) {
  506.                                     TextField("Please enter station name", text: $station6)
  507.                                     TextField("Please enter line name", text: $line6)
  508.                                     DatePicker("Departure",selection: $time6, displayedComponents: .hourAndMinute)
  509.                                 }
  510.                             }
  511.                                 Section(header: Text("Arriving")) {
  512.                                     TextField("Please enter station name", text: $station7)
  513.                                     DatePicker("Arriving at",selection: $time7, displayedComponents: .hourAndMinute)
  514.                                 }
  515.                             Button(action: {
  516.                                 let newMove = Move (context: viewContext)
  517.                                 newMove.id = UUID()
  518.                                 newMove.station = self.station
  519.                                 newMove.line = self.line
  520.                                 newMove.time = self.time
  521.                                 newMove.station2 = self.station2
  522.                                 newMove.line2 = self.line2
  523.                                 newMove.time2 = self.time2
  524.                                 newMove.station3 = self.station3
  525.                                 newMove.line3 = self.line3
  526.                                 newMove.time3 = self.time3
  527.                                 newMove.station4 = self.station4
  528.                                 newMove.line4 = self.line4
  529.                                 newMove.time4 = self.time4
  530.                                 newMove.station5 = self.station5
  531.                                 newMove.line5 = self.line5
  532.                                 newMove.time5 = self.time5
  533.                                 newMove.station6 = self.station6
  534.                                 newMove.line6 = self.line6
  535.                                 newMove.time6 = self.time6
  536.                                 newMove.station7 = self.station7
  537.                                 newMove.time7 = self.time7
  538.                                
  539.                                 do {
  540.                                    try viewContext.save()
  541.                                     presentationMode.wrappedValue.dismiss()
  542.                                 } catch {
  543.                                     let error = error as NSError
  544.                                     fatalError("Unresolved Error: \(error)")
  545.                                   }
  546.                                 }, label: {
  547.                                 Text("Save")
  548.                             })
  549.                         }
  550.                     }
  551.               }
  552.             else if self.categoryIndex == 3 {
  553.                 Form {
  554.                     Section(header: Text("Belongings")) {
  555.                         TextField("Please enter things you should bring", text: $belonging )
  556.                     }
  557.                     Button(action: {
  558.                         let newBelonging = Belonging (context: viewContext)
  559.                         newBelonging.belonging = self.belonging
  560.                         newBelonging.id = UUID()
  561.                         do {
  562.                            try viewContext.save()
  563.                             presentationMode.wrappedValue.dismiss()
  564.                         } catch {
  565.                             let error = error as NSError
  566.                             fatalError("Unresolved Error: \(error)")
  567.                           }
  568.                         }, label: {
  569.                         Text("Save")
  570.                     })
  571.                 }
  572.             }
  573.             else if self.categoryIndex == 4 {
  574.                 Form {
  575.                     Section(header: Text("Memo")) {
  576.                         TextField("Please make a memo", text:$memo )
  577.                     }
  578.                     Button(action: {
  579.                         let newMemo = Memo (context: viewContext)
  580.                         newMemo.memo = self.memo
  581.                         newMemo.id = UUID()
  582.                         do {
  583.                            try viewContext.save()
  584.                             presentationMode.wrappedValue.dismiss()
  585.                         } catch {
  586.                             let error = error as NSError
  587.                             fatalError("Unresolved Error: \(error)")
  588.                           }
  589.                         }, label: {
  590.                         Text("Save")
  591.                     })
  592.                 }
  593.             }
  594.         }
  595.     }
  596. }
  597. // frame
  598. import SwiftUI
  599. struct todoFrame: View {
  600.     var todoItem: Todo
  601.     let todoDateFormat: DateFormatter = {
  602.             let formatter = DateFormatter()
  603.             formatter.timeStyle = .short
  604.             return formatter
  605.         }()
  606.     var body: some View {
  607.           VStack(alignment:.center) {
  608.             Text(todoItem.todo!)
  609.                 .font(.system(size: 23))
  610.             Divider()
  611.             if todoItem.place != "" {
  612.             Text("\(todoItem.place!)").font(.system(size: 15))
  613.             }
  614.             HStack {
  615.                 Text(" \(todoItem.start!, formatter: self.todoDateFormat)")
  616.                 Text("-")
  617.                 Text(" \(todoItem.end!, formatter: self.todoDateFormat)")
  618.             }.font(.system(size: 15))
  619.             if todoItem.cost != "" {
  620.             Text("\(todoItem.cost!)").font(.system(size: 15))
  621.             }
  622.           }
  623.         .frame(width: 200, height: 200)
  624.         .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
  625.         .cornerRadius(10)
  626.     }
  627. }
  628. struct wantFrame: View {
  629.     var wantItem: Want
  630.     let wantDateFormat: DateFormatter = {
  631.             let formatter = DateFormatter()
  632.             formatter.timeStyle = .short
  633.             return formatter
  634.         }()
  635.     var body: some View {
  636.           VStack(alignment:.center) {
  637.             Text(wantItem.want!)
  638.                 .font(.system(size: 23))
  639.             Divider()
  640.             if wantItem.place2 != "" {
  641.             Text("\(wantItem.place2!)").font(.system(size: 15))
  642.             }
  643.             HStack {
  644.                 Text(" \(wantItem.start2!, formatter: self.wantDateFormat)")
  645.                 Text("-")
  646.                 Text(" \(wantItem.end2!, formatter: self.wantDateFormat)")
  647.             }.font(.system(size: 15))
  648.             if wantItem.cost2 != "" {
  649.             Text("\(wantItem.cost2!)").font(.system(size: 15))
  650.             }
  651.           }.padding()
  652.         .frame(width: 200, height: 200)
  653.         .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
  654.         .cornerRadius(10)
  655.     }
  656. }
  657. struct moveFrame: View {
  658.     var moveItem: Move
  659.     let moveDateFormat: DateFormatter = {
  660.             let formatter = DateFormatter()
  661.             formatter.timeStyle = .short
  662.             return formatter
  663.         }()
  664.     
  665.     var body: some View {
  666.         Group {
  667.             Group {
  668.                 Text("\(moveItem.station!)(\(moveItem.line!))").font(.system(size: 23))
  669.                 Text("\(moveItem.time!, formatter: self.moveDateFormat)").font(.system(size: 15))
  670.                 Text("↓")
  671.             }
  672.             if moveItem.station2 != "" {
  673.                 Group {
  674.                     Text("\(moveItem.station2!)(\(moveItem.line2!))").font(.system(size: 23))
  675.                     Text("\(moveItem.time2!, formatter: self.moveDateFormat)").font(.system(size: 15))
  676.                     Text("↓")
  677.                 }
  678.             }
  679.             if moveItem.station3 != "" {
  680.                 Group {
  681.                     Text("\(moveItem.station3!)(\(moveItem.line3!))").font(.system(size: 23))
  682.                     Text(" \(moveItem.time3!, formatter: self.moveDateFormat)").font(.system(size: 15))
  683.                     Text("↓")
  684.                 }
  685.             }
  686.             if moveItem.station4 != "" {
  687.                 Group {
  688.                     Text("\(moveItem.station4!)(\(moveItem.line4!))").font(.system(size: 23))
  689.                     Text("\(moveItem.time4!, formatter: self.moveDateFormat)").font(.system(size: 15))
  690.                     Text("↓")
  691.                 }
  692.             }
  693.             if moveItem.station5 != "" {
  694.                 Group {
  695.                     Text("\(moveItem.station5!)(\(moveItem.line5!))").font(.system(size: 23))
  696.                     Text("\(moveItem.time5!, formatter: self.moveDateFormat)").font(.system(size: 15))
  697.                     Text("↓")
  698.                 }
  699.             }
  700.             if moveItem.station6 != "" {
  701.                 Group {
  702.                     Text("\(moveItem.station6!)(\(moveItem.line6!))").font(.system(size: 23))
  703.                     Text("\(moveItem.time6!, formatter: self.moveDateFormat)").font(.system(size: 15))
  704.                     Text("↓")
  705.                 }
  706.             }
  707.             Text("\(moveItem.station7!)").font(.system(size: 23))
  708.             Text(" \(moveItem.time7!, formatter: self.moveDateFormat)").font(.system(size: 15))
  709.         }
  710.         .frame(width: 200, height: 200)
  711.         .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
  712.         .cornerRadius(10)
  713.     }
  714. }
  715. struct belongingFrame: View {
  716.     var belongingItem: Belonging
  717.     var body: some View {
  718.         Text(belongingItem.belonging!)
  719.             .frame(width: 200, height: 200)
  720.             .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
  721.             .cornerRadius(10)
  722.     }
  723. }
  724. struct memoFrame: View {
  725.     var memoItem: Memo
  726.     var body: some View {
  727.         Text(memoItem.memo!)
  728.             .frame(width: 200, height: 200)
  729.             .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
  730.             .cornerRadius(10)
  731.     }
  732. }
  733. // Persistence
  734. import CoreData
  735. struct PersistenceController {
  736.     static let shared = PersistenceController()
  737.     let container: NSPersistentContainer
  738.     init(inMemory: Bool = false) {
  739.         container = NSPersistentContainer(name: "DesignGo")
  740.         if inMemory {
  741.             container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
  742.         }
  743.         container.loadPersistentStores(completionHandler: { (storeDescription, error) in
  744.             if let error = error as NSError? {
  745.                 // Replace this implementation with code to handle the error appropriately.
  746.                 // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
  747.                 /*
  748.                 Typical reasons for an error here include:
  749.                 * The parent directory does not exist, cannot be created, or disallows writing.
  750.                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
  751.                 * The device is out of space.
  752.                 * The store could not be migrated to the current model version.
  753.                 Check the error message to determine what the actual problem was.
  754.                 */
  755.                 fatalError("Unresolved error \(error), \(error.userInfo)")
  756.             }
  757.         })
  758.     }
  759. }

Digital Time Capsule

  1. // DesignMapApp
  2. import SwiftUI
  3. import CoreLocation
  4. @main
  5. struct DesignMapApp: App {
  6.     let persistenceController = PersistenceController.shared
  7.     
  8.     var body: some Scene {
  9.         WindowGroup {
  10.             ContentView(locationSearchService: LocationSearchService())
  11.                 .environment(\.managedObjectContext, persistenceController.container.viewContext)
  12.         }
  13.     }
  14. }
  15. // ContentView
  16. import SwiftUI
  17. import CoreData
  18. import MapKit
  19. import CoreLocation
  20. import UIKit
  21. struct ContentView: View {
  22.     
  23.     @Environment(\.managedObjectContext) private var viewContext
  24.     @FetchRequest(sortDescriptors: [])
  25.     private var timeCapsules: FetchedResults<TimeCapsule>
  26.     
  27.     
  28.     let geoCoder = CLGeocoder()
  29.     @ObservedObject var locationSearchService: LocationSearchService
  30.     @State var address = ""
  31.     @State var addressCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 35.652832, longitude: 139.839478)
  32.     @ObservedObject var locationManager = LocationManager()
  33.     @State var showingSheet = false
  34.     public static var add = false
  35.     @State var showMessage = false
  36.     
  37.     var body: some View {
  38.         NavigationView {
  39.             ZStack {
  40.                     VStack {
  41.                         /*
  42.                          SearchBar(text: $locationSearchService.searchQuery)
  43.                         if locationSearchService.searchQuery != "" {
  44.                             List(locationSearchService.completions) { completion in
  45.                                 Button(action: {
  46.                                     address = completion.subtitle
  47.                                     geoCoder.geocodeAddressString(address) { (placemarks, error) in
  48.                                            guard
  49.                                                let placemarks = placemarks,
  50.                                                let location = placemarks.first?.location
  51.                                            else {
  52.                                                // handle no location found
  53.                                                return
  54.                                            }
  55.                                         let coordinate = location.coordinate
  56.                                         addressCoordinate = coordinate
  57.                                     }
  58.                                 }){
  59.                                         VStack(alignment: .leading) {
  60.                                             Text(completion.title)
  61.                                             Text(completion.subtitle)
  62.                                                 .font(.subheadline)
  63.                                                 .foregroundColor(.gray)
  64.                                     }
  65.                                 }
  66.                             }
  67.                         }
  68.                          */
  69.                         ContentView.MapView(coordinate: CLLocationCoordinate2D(latitude: locationManager.lastLocation?.coordinate.latitude ?? 0, longitude: locationManager.lastLocation?.coordinate.longitude ?? 0))
  70.                             .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
  71.                         
  72.                     }
  73. /*
  74.                 GeometryReader { geometry in
  75.                     Text(address)
  76.                         .frame(width: 300, height: /*@START_MENU_TOKEN@*/100/*@END_MENU_TOKEN@*/, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
  77.                         .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
  78.                         .cornerRadius(10)
  79.                         .position(x:geometry.frame(in: .global).maxX/2 , y:geometry.frame(in: .global).maxY-90)
  80.                }
  81.                  */
  82.                 
  83.                 GeometryReader { geometry in
  84.                     Button(action:{
  85.                         self.showingSheet.toggle()
  86.                     }) {
  87.                         Circle()
  88.                             .frame(width: 50, height: 50)
  89.                     }.position(x:geometry.frame(in: .global).maxX-50 , y:geometry.frame(in: .global).maxY-170)
  90.                     
  91.                     NavigationLink(destination: TimeCapsuleList(), label: {
  92.                         Circle()
  93.                             .frame(width: 50, height: 50)
  94.                                })
  95.                     .position(x:geometry.frame(in: .global).maxX-50 , y:geometry.frame(in: .global).maxY-230)
  96.                     
  97.                 }
  98.                     
  99.                 GeometryReader { geometry in
  100.                     ForEach(timeCapsules){timeCapsule in
  101.                         if timeCapsule.latitude == locationManager.lastLocation?.coordinate.latitude && timeCapsule.longitude == locationManager.lastLocation?.coordinate.longitude &&
  102.                            timeCapsule.date! <= Date()
  103.                         {
  104.                             Button(action:{
  105.                                 showMessage = true
  106.                             }){
  107.                                 Text("Open")
  108.                                     .fontWeight(.heavy)
  109.                                     .foregroundColor(.white)
  110.                                     .frame(width:200,height:50)
  111.                                     .background(Color(red: 1, green: 0, blue: 0, opacity: 1))
  112.                                     .cornerRadius(10)
  113.                             } .position(x:geometry.frame(in: .global).maxX/2 , y:geometry.frame(in: .global).maxY-170)
  114.                             
  115.                             if showMessage == true {
  116.                                 Message(timeCapsule: timeCapsule)
  117.                                     .position(x:geometry.frame(in: .global).maxX/2 , y:geometry.frame(in: .global).maxY-550)
  118.                                     .gesture(
  119.                                     TapGesture()
  120.                                         .onEnded { _ in
  121.                                             showMessage = false
  122.                                             viewContext.delete(timeCapsule)
  123.                                             try! viewContext.save()
  124.                                         }
  125.                                         )
  126.                             }
  127.                         }
  128.                     }
  129.             
  130.                 }
  131.             }.sheet(isPresented: $showingSheet) {
  132.                 settingSheet()
  133.         }
  134.         }
  135.     
  136. }
  137.     
  138.     
  139.     
  140.     //Mapview------------------------------------------------------------------------------------
  141.     struct MapView : UIViewRepresentable {
  142.         
  143.         let locationManager = CLLocationManager()
  144.         var coordinate: CLLocationCoordinate2D
  145.         let map = MKMapView()
  146.         @ObservedObject var locationManager2 = LocationManager()
  147.         
  148.         @Environment(\.managedObjectContext) private var viewContext
  149.         @FetchRequest(sortDescriptors: [])
  150.         private var timeCapsules: FetchedResults<TimeCapsule>
  151.         
  152.         @FetchRequest(sortDescriptors: [])
  153.         private var pins: FetchedResults<Pin>
  154.         
  155.         
  156.         func makeUIView(context: UIViewRepresentableContext<MapView>) -> MKMapView {
  157.             
  158.             let coordinate = CLLocationCoordinate2D(latitude: locationManager2.lastLocation?.coordinate.latitude ?? 0, longitude: locationManager2.lastLocation?.coordinate.longitude ?? 0)
  159.             
  160.             map.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 50000, longitudinalMeters: 50000)
  161.             
  162.             for i in pins {
  163.                 let pinCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: i.pinLatitude ,longitude: i.pinLongitude)
  164.                 let pinAnnotaion = MKPointAnnotation()
  165.                 pinAnnotaion.coordinate = pinCoordinate
  166.                 map.addAnnotation(pinAnnotaion)
  167.             }
  168.                
  169.         
  170.             
  171.             return map
  172.         }
  173.         func updateUIView(_ uiView: MKMapView, context: UIViewRepresentableContext<MapView>) {
  174.             uiView.showsUserLocation = true
  175.                    locationManager.requestAlwaysAuthorization()
  176.                    locationManager.requestWhenInUseAuthorization()
  177.             
  178.             uiView.setCenter(coordinate, animated: true)
  179.             
  180.             let currentCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: locationManager2.lastLocation?.coordinate.latitude ?? 0, longitude: locationManager2.lastLocation?.coordinate.longitude ?? 0)
  181.             
  182.             let currentAnnotaion = MKPointAnnotation()
  183.             currentAnnotaion.title = ""
  184.             currentAnnotaion.subtitle = ""
  185.             
  186.         
  187.             currentAnnotaion.coordinate = currentCoordinate
  188.             
  189.             if ContentView.add == true {
  190.                 uiView.addAnnotation(currentAnnotaion)}
  191.             
  192.             let newPin = Pin (context: viewContext)
  193.             newPin.pinLatitude = locationManager2.lastLocation?.coordinate.latitude ?? 0
  194.             newPin.pinLongitude = locationManager2.lastLocation?.coordinate.longitude ?? 0
  195.             
  196.             do {
  197.                try viewContext.save()
  198.                 ContentView.add = true
  199.             } catch {
  200.                 let error = error as NSError
  201.                 fatalError("Unresolved Error: \(error)")
  202.               }
  203.         }
  204.         func makeCoordinator() -> Coordinator {
  205.             return Coordinator(self)
  206.         }
  207.         class Coordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate {
  208.             var parent: MapView
  209.             var gRecognizer = UITapGestureRecognizer()
  210.             init(_ parent: MapView) {
  211.                 self.parent = parent
  212.                 super.init()
  213.                 self.gRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapHandler))
  214.                 self.gRecognizer.delegate = self
  215.                 self.parent.map.addGestureRecognizer(gRecognizer)
  216.                 
  217.             }
  218.             
  219.             @objc func tapHandler(_ gesture: UITapGestureRecognizer) {
  220.                 let location = gRecognizer.location(in: self.parent.map)
  221.                 let coordinate = self.parent.map.convert(location, toCoordinateFrom: self.parent.map)
  222.                 self.parent.map.setCenter(coordinate, animated: true)
  223.                 
  224.             }
  225.         }
  226.     }
  227. }
  228. struct Message: View {
  229.     
  230.     @Environment(\.managedObjectContext) private var viewContext
  231.      var timeCapsule: TimeCapsule
  232.     @ObservedObject var locationManager = LocationManager()
  233.     
  234.     var body: some View {
  235.         Text(timeCapsule.message!)
  236.             .frame(width: 300, height: 400)
  237.             .background(Color(red: 1, green: 1, blue: 1))
  238.     }
  239. }
  240. // TimecapsuleList
  241. import SwiftUI
  242. struct TimeCapsuleList: View {
  243.     
  244.     @Environment(\.managedObjectContext) private var viewContext
  245.     @FetchRequest(sortDescriptors: [])
  246.     private var timeCapsules: FetchedResults<TimeCapsule>
  247.     let dateFormat: DateFormatter = {
  248.             let formatter = DateFormatter()
  249.             formatter.dateStyle = .medium
  250.             return formatter
  251.         }()
  252.     
  253.     
  254.     var body: some View {
  255.         
  256.         VStack(){
  257.             Text("Your Time Capsules List")
  258.                 .font(.title)
  259.             List {
  260.                 ForEach(timeCapsules){timeCapsule in
  261.                     TimeCapsuleListFrame(timecapsule: timeCapsule)
  262.                         .contextMenu {
  263.                             Button(action:{
  264.                                     withAnimation{
  265.                                         viewContext.delete(timeCapsule)
  266.                                         try! viewContext.save()
  267.                                     }
  268.                             }, label: {
  269.                                 Text("Delete")})
  270.                         }
  271.                     }
  272.             }
  273.         }
  274.     }
  275. }
  276. struct TimeCapsuleListFrame : View {
  277.     
  278.     var timecapsule:TimeCapsule
  279.     let dateFormat: DateFormatter = {
  280.             let formatter = DateFormatter()
  281.             formatter.dateStyle = .medium
  282.             return formatter
  283.         }()
  284.     let date = Date()
  285.     
  286.     var body: some View {
  287.         VStack(alignment:.leading){
  288.             Text(timecapsule.place!)
  289.                 .font(.body)
  290.             Text("( Buried on \(date,formatter: self.dateFormat), Available from \(timecapsule.date!, formatter: self.dateFormat))")
  291.                 .font(.caption)
  292.         }
  293.     }
  294. }
  295. // settingSheet
  296. import SwiftUI
  297. import CoreLocation
  298. struct settingSheet: View {
  299.     
  300.     @Environment (\.presentationMode) var presentationMode
  301.     @FetchRequest(sortDescriptors: [])
  302.     private var timeCapsules: FetchedResults<TimeCapsule>
  303.     
  304.     @State var date = Date()
  305.     @State var message = ""
  306.     @State var longitude: Double = 0
  307.     @State var latitude: Double = 0
  308.     @State var place = ""
  309.     
  310.     
  311.     @ObservedObject var locationManager = LocationManager()
  312.     @Environment(\.managedObjectContext) private var viewContext
  313.     
  314.     @State var showingAlert = false
  315.    
  316.     
  317.     var body: some View {
  318.         
  319.         VStack{
  320.             Form{
  321.                 Text("Message for future")
  322.                 TextEditor(text: $message)
  323.                 .foregroundColor(.black)
  324.                 .frame(width: 250, height: 200, alignment: .center)
  325.                 
  326.                 TextField("Place",text: $place)
  327.                 DatePicker("Days after...",selection: $date, displayedComponents: .date)
  328.                 
  329.                 Button(action:{
  330.                     let newTimeCapsule = TimeCapsule (context: viewContext)
  331.                     newTimeCapsule.message = self.message
  332.                     newTimeCapsule.id = UUID()
  333.                     newTimeCapsule.date = self.date
  334.                     newTimeCapsule.place = self.place
  335.                     newTimeCapsule.latitude = locationManager.lastLocation?.coordinate.latitude ?? 0
  336.                     newTimeCapsule.longitude = locationManager.lastLocation?.coordinate.longitude ?? 0
  337.                     
  338.                     do {
  339.                        try viewContext.save()
  340.                         ContentView.add = true
  341.                     } catch {
  342.                         let error = error as NSError
  343.                         fatalError("Unresolved Error: \(error)")
  344.                       }
  345.                     showingAlert = true
  346.                 }){
  347.                    Text("Save")
  348.                 }.alert(isPresented: $showingAlert) {
  349.                     Alert(title: Text("Complete"),
  350.                           message: Text("Your time capsule is buried. Please visit here after set time "),
  351.                           dismissButton: .default(Text("OK"),
  352.                                                   action: {
  353.                                                     ContentView.add = false
  354.                                                     presentationMode.wrappedValue.dismiss()
  355.                                                   }))
  356.                 }
  357.             }
  358.         }
  359.     }
  360. }
  361. struct TextView: UIViewRepresentable {
  362.     @Binding var text: String
  363.     func makeCoordinator() -> Coordinator {
  364.         Coordinator(self)
  365.     }
  366.     func makeUIView(context: Context) -> UITextView {
  367.         let myTextView = UITextView()
  368.         myTextView.delegate = context.coordinator
  369.         myTextView.font = UIFont(name: "HelveticaNeue", size: 15)
  370.         myTextView.isScrollEnabled = true
  371.         myTextView.isEditable = true
  372.         myTextView.isUserInteractionEnabled = true
  373.         myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)
  374.         return myTextView
  375.     }
  376.     func updateUIView(_ uiView: UITextView, context: Context) {
  377.         uiView.text = text
  378.     }
  379.     class Coordinator : NSObject, UITextViewDelegate {
  380.         var parent: TextView
  381.         init(_ uiTextView: TextView) {
  382.             self.parent = uiTextView
  383.         }
  384.         func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
  385.             return true
  386.         }
  387.         func textViewDidChange(_ textView: UITextView) {
  388.             print("text now: \(String(describing: textView.text!))")
  389.             self.parent.text = textView.text
  390.         }
  391.     }
  392. }
  393. //LocationManager
  394. import Foundation
  395. import CoreLocation
  396. import Combine
  397. class LocationManager: NSObject, ObservableObject {
  398.     override init() {
  399.         super.init()
  400.         self.locationManager.delegate = self
  401.         self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
  402.         self.locationManager.requestWhenInUseAuthorization()
  403.         self.locationManager.startUpdatingLocation()
  404.     }
  405.     @Published var locationStatus: CLAuthorizationStatus? {
  406.         willSet {
  407.             objectWillChange.send()
  408.         }
  409.     }
  410.     @Published var lastLocation: CLLocation? {
  411.         willSet {
  412.             objectWillChange.send()
  413.         }
  414.     }
  415.     var statusString: String {
  416.         guard let status = locationStatus else {
  417.             return "unknown"
  418.         }
  419.         switch status {
  420.         case .notDetermined: return "notDetermined"
  421.         case .authorizedWhenInUse: return "authorizedWhenInUse"
  422.         case .authorizedAlways: return "authorizedAlways"
  423.         case .restricted: return "restricted"
  424.         case .denied: return "denied"
  425.         default: return "unknown"
  426.         }
  427.     }
  428.     let objectWillChange = PassthroughSubject<Void, Never>()
  429.     private let locationManager = CLLocationManager()
  430. }
  431. extension LocationManager: CLLocationManagerDelegate {
  432.     func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
  433.         self.locationStatus = status
  434.         print(#function, statusString)
  435.     }
  436.     func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
  437.         guard let location = locations.last else { return }
  438.         self.lastLocation = location
  439.         print(#function, location)
  440.     }
  441. }
  442. // Persistence
  443. import CoreData
  444. struct PersistenceController {
  445.     static let shared = PersistenceController()
  446.     
  447.     let container: NSPersistentContainer
  448.     init(inMemory: Bool = false) {
  449.         container = NSPersistentContainer(name: "DesignMap")
  450.         if inMemory {
  451.             container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
  452.         }
  453.         container.loadPersistentStores(completionHandler: { (storeDescription, error) in
  454.             if let error = error as NSError? {
  455.                 // Replace this implementation with code to handle the error appropriately.
  456.                 // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
  457.                 /*
  458.                 Typical reasons for an error here include:
  459.                 * The parent directory does not exist, cannot be created, or disallows writing.
  460.                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
  461.                 * The device is out of space.
  462.                 * The store could not be migrated to the current model version.
  463.                 Check the error message to determine what the actual problem was.
  464.                 */
  465.                 fatalError("Unresolved error \(error), \(error.userInfo)")
  466.             }
  467.         })
  468.     }
  469. }