二つのアプリの9割が完成したので(簡単な仕上げを残して)、コードを以下に記す。デザインや詳細機能は発表で紹介する。
DesignGo
- // DesignGoApp
- import SwiftUI
- @main
- struct DesignGoApp: App {
- let persistenceController = PersistenceController.shared
- var body: some Scene {
- WindowGroup {
- ContentView()
- .environment(\.managedObjectContext, persistenceController.container.viewContext)
- }
- }
- }
- // ContentView
- import SwiftUI
- import CoreData
- struct ContentView: View {
-
- @Environment(\.managedObjectContext) private var viewContext
-
- @State var showingSheet = false
-
- @FetchRequest(sortDescriptors: [])
- private var todos: FetchedResults<Todo>
-
- @FetchRequest(sortDescriptors: [])
- private var wants: FetchedResults<Want>
-
- @FetchRequest(sortDescriptors: [])
- private var moves: FetchedResults<Move>
-
- @FetchRequest(sortDescriptors: [])
- private var belongings: FetchedResults<Belonging>
-
- @FetchRequest(sortDescriptors: [])
- private var memos: FetchedResults<Memo>
-
- @State var randomInt = 0
-
- @State var showAnimation = false
-
- var body: some View {
- ZStack {
- Color(red: 0.97, green: 0.97, blue: 0.95).edgesIgnoringSafeArea(.all)
- if todos.count == 0 && wants.count == 0 && moves.count == 0 && belongings.count == 0 && memos.count == 0 {
- Text("Design your life !").font(.largeTitle)
- }
- ScrollView {
- VStack(alignment: .leading, spacing: 20) {
- Group {
- if todos.count != 0 {
- Text("todos(\(todos.count))")
- .fontWeight(.medium)
- .offset(x: 10, y: 10)
- .font(.title)
- }
-
- ScrollView(.horizontal, showsIndicators: false){
- HStack {
- ForEach(todos){ todo in
- todoFrame(todoItem: todo)
- .padding()
- .contextMenu {
- Button(action:{
- withAnimation{
- viewContext.delete(todo)
- self.randomInt = Int.random(in: 0..<2)
- try! viewContext.save()
- }
- }, label: {
- Text("Done")})
- Button(action: {
- withAnimation {
- viewContext.delete(todo)
- try! viewContext.save()
- }
- }, label: {
- Text("Delete")})
- }
- }
- }
- }.offset(x: 2)
- }
- Group {
- if wants.count != 0 {
- Text("wants(\(wants.count))")
- .fontWeight(.medium)
- .offset(x: 10, y: 10)
- .font(.title)
- }
-
- ScrollView(.horizontal, showsIndicators: false){
- HStack {
- ForEach(wants){ want in
- wantFrame(wantItem: want)
- .padding()
- .contextMenu {
- Button(action:{
- withAnimation{
- viewContext.delete(want)
- self.randomInt = Int.random(in: 0..<2)
- try! viewContext.save()
- }
- }, label: {
- Text("Done")})
- Button(action: {
- withAnimation {
- viewContext.delete(want)
- try! viewContext.save()
- }
- }, label: {
- Text("Delete")})
- }
- }
- }
- }.offset(x: 2)
- }
- Group {
- if moves.count != 0 {
- Text("moves(\(moves.count))")
- .fontWeight(.medium)
- .offset(x: 10, y: 10)
- .font(.title)
- }
- ScrollView(.horizontal, showsIndicators: false){
- HStack {
- ForEach(moves){ move in
- moveFrame(moveItem: move)
- .padding()
- .contextMenu {
- Button(action:{
- withAnimation{
- viewContext.delete(move)
- self.randomInt = Int.random(in: 0..<2)
- try! viewContext.save()
- }
- }, label: {
- Text("Done")})
- Button(action: {
- withAnimation {
- viewContext.delete(move)
- try! viewContext.save()
- }
- }, label: {
- Text("Delete")})
- }
- }
- }
- }.offset(x: 2)
- }
- Group {
- if belongings.count != 0 {
- Text("belongings(\(belongings.count))")
- .fontWeight(.medium)
- .offset(x: 10, y: 10)
- .font(.title)
- }
- ScrollView(.horizontal, showsIndicators: false){
- HStack {
- ForEach(belongings){ belonging in
- belongingFrame(belongingItem: belonging)
- .padding()
- .contextMenu {
- Button(action:{
- withAnimation{
- viewContext.delete(belonging)
- self.randomInt = Int.random(in: 0..<2)
- try! viewContext.save()
- }
- }, label: {
- Text("Done")})
- Button(action: {
- withAnimation {
- viewContext.delete(belonging)
- try! viewContext.save()
- }
- }, label: {
- Text("Delete")})
- }
- }
- }
- }.offset(x: 2)
- }
- Group {
- if memos.count != 0 {
- Text("memos(\(memos.count))")
- .fontWeight(.medium)
- .offset(x: 10, y: 10)
- .font(.title)
- }
- ScrollView(.horizontal, showsIndicators: false){
- HStack {
- ForEach(memos){ memo in
- memoFrame(memoItem: memo)
- .padding()
- .contextMenu {
- Button(action:{
- withAnimation{
- viewContext.delete(memo)
- self.randomInt = Int.random(in: 0..<2)
- try! viewContext.save()
- }
- }, label: {
- Text("Done")})
- Button(action: {
- withAnimation {
- viewContext.delete(memo)
- try! viewContext.save()
- }
- }, label: {
- Text("Delete")})
- }
- }
- }
- }.offset(x: 2)
- }
- }
- }.sheet(isPresented: $showingSheet) {
- settingSheet()
- }
- GeometryReader { geometry in
- Button(action: {self.showingSheet.toggle()}){
- Circle()
- .fill(buttonColor)
- .frame(width: 60, height: 60)
- .shadow(radius: 10, x: 5, y: 5)
- }.position(x:geometry.frame(in: .global).maxX-50 , y:geometry.frame(in: .global).maxY-70)
- }
- if randomInt == 1 {
- withAnimation {
- Animation().edgesIgnoringSafeArea(.all)
- .gesture(
- TapGesture()
- .onEnded { _ in
- self.randomInt = 0
- }
- )
- }
- }
- }
- }
- }
- fileprivate let gradientColors = Gradient(colors: [.yellow, .white, .orange])
- fileprivate let buttonColor = AngularGradient(gradient: gradientColors, center: .center)
- // Animation
- import SwiftUI
- struct Animation: View {
- var body: some View {
- ZStack {
- Color(red: 0, green: 0, blue: 0, opacity: 0.8)
- LottieView()
- }
- }
- }
- // LottieView
- import SwiftUI
- import Lottie
- struct LottieView: UIViewRepresentable {
-
- typealias UIViewType = UIView
-
- var name = "fireworks"
-
- func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
- let view = AnimationView(name: name, bundle: Bundle.main)
- view.play()
- return view
- }
-
- func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
- }
- }
- // settingSheet
- import SwiftUI
- struct settingSheet: View {
-
- @Environment(\.managedObjectContext) private var viewContext
- @Environment (\.presentationMode) var presentationMode
-
- let categories = ["Todo","Want","Move","Belonging","Memo"]
- @State var categoryIndex = 0
-
- @FetchRequest(sortDescriptors: [])
- private var todos: FetchedResults<Todo>
- @State var todo = ""
- @State var place = ""
- @State var start = Date()
- @State var end = Date()
- @State var todoCategoryIndex = 0
- @State var cost = ""
- let todoCategories = ["","study","work","shopping"]
-
- @FetchRequest(sortDescriptors: [])
- private var wants: FetchedResults<Want>
- @State var want = ""
- @State var place2 = ""
- @State var start2 = Date()
- @State var end2 = Date()
- @State var wantCategoryIndex = 0
- @State var cost2 = ""
- let wantCategories = ["","study","work","shopping"]
-
- @FetchRequest(sortDescriptors: [])
- private var moves: FetchedResults<Move>
- @State var howManyTransfer = 0
- @State var station = ""
- @State var line = ""
- @State var time = Date()
-
- @State var station2 = ""
- @State var line2 = ""
- @State var time2 = Date()
- @State var station3 = ""
- @State var line3 = ""
- @State var time3 = Date()
- @State var station4 = ""
- @State var line4 = ""
- @State var time4 = Date()
- @State var station5 = ""
- @State var line5 = ""
- @State var time5 = Date()
- @State var station6 = ""
- @State var line6 = ""
- @State var time6 = Date()
- @State var station7 = ""
- @State var time7 = Date()
-
- @FetchRequest(sortDescriptors: [])
- private var belongings: FetchedResults<Belonging>
- @State var belonging = ""
-
- @FetchRequest(sortDescriptors: [])
- private var memos: FetchedResults<Memo>
- @State var memo = ""
-
- var body: some View {
-
- VStack(){
- Picker(selection: $categoryIndex, label: Text("choose a category")) {
- ForEach(0 ..< categories.count) {
- Text(self.categories[$0]).tag($0)
- }
- }
- if self.categoryIndex == 0 {
- Form {
- Section(header: Text("todo deatils")) {
- TextField("Please enter todo", text: $todo)
- TextField("Please enter place", text: $place)
- TextField("How much does it cost?", text: $cost).keyboardType(.numberPad)
- Picker(selection: $todoCategoryIndex, label: Text("category")) { ForEach(0 ..< todoCategories.count) {
- Text(self.todoCategories[$0]).tag($0)
- }
- }.pickerStyle(WheelPickerStyle())
- DatePicker("from",selection: $start)
- DatePicker("to",selection: $end)
- }
- Button(action: {
- let newTodo = Todo (context: viewContext)
- newTodo.todo = self.todo
- newTodo.category = self.categories[self.categoryIndex]
- newTodo.place = self.place
- newTodo.id = UUID()
- newTodo.start = self.start
- newTodo.end = self.end
- newTodo.cost = self.cost
-
- do {
- try viewContext.save()
- presentationMode.wrappedValue.dismiss()
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- }, label: {
- Text("Save")
- })
- }
- }
- else if self.categoryIndex == 1 {
- Form {
- Section(header: Text("want deatils")) {
- TextField("Please enter want", text: $want)
- TextField("Please enter place", text: $place2)
- TextField("How much does it cost?", text: $cost2).keyboardType(.numberPad)
- Picker(selection: $wantCategoryIndex, label: Text("category")) { ForEach(0 ..< wantCategories.count) {
- Text(self.wantCategories[$0]).tag($0)
- }
- }.pickerStyle(WheelPickerStyle())
- DatePicker("from",selection: $start2)
- DatePicker("to",selection: $end2)
- }
- Button(action: {
- let newWant = Want (context: viewContext)
- newWant.want = self.want
- newWant.category2 = self.categories[self.categoryIndex]
- newWant.place2 = self.place
- newWant.id = UUID()
- newWant.start2 = self.start2
- newWant.end2 = self.end2
- newWant.cost2 = self.cost2
-
- do {
- try viewContext.save()
- presentationMode.wrappedValue.dismiss()
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- }, label: {
- Text("Save")
- })
- }
- }
- else if self.categoryIndex == 2 {
- VStack {
- Form {
- Section(header: Text("how many transfers ?")) {
- Stepper(value: $howManyTransfer ,in: 0...4) {
- Text(" \(howManyTransfer) \(howManyTransfer == 0 ? "transfer" : "transfers")").padding()
- }
- }
- Section(header: Text("Departure")) {
- TextField("Please enter station name", text: $station)
- TextField("Please enter line name", text: $line)
- DatePicker("Departing at",selection: $time, displayedComponents: .hourAndMinute)
- }
- if howManyTransfer == 1 {
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station2)
- TextField("Please enter line name", text: $line2)
- DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
- }
- }
- else if howManyTransfer == 2 {
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station2)
- TextField("Please enter line name", text: $line2)
- DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station3)
- TextField("Please enter line name", text: $line3)
- DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
- }
- }
- else if howManyTransfer == 3 {
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station2)
- TextField("Please enter line name", text: $line2)
- DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station3)
- TextField("Please enter line name", text: $line3)
- DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station4)
- TextField("Please enter line name", text: $line4)
- DatePicker("Departure",selection: $time4, displayedComponents: .hourAndMinute)
- }
- }
- else if howManyTransfer == 4 {
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station2)
- TextField("Please enter line name", text: $line2)
- DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station3)
- TextField("Please enter line name", text: $line3)
- DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station4)
- TextField("Please enter line name", text: $line4)
- DatePicker("Departure",selection: $time4, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station5)
- TextField("Please enter line name", text: $line5)
- DatePicker("Departure",selection: $time5, displayedComponents: .hourAndMinute)
- }
- }
- else if howManyTransfer == 5 {
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station2)
- TextField("Please enter line name", text: $line2)
- DatePicker("Departure",selection: $time2, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station3)
- TextField("Please enter line name", text: $line3)
- DatePicker("Departure",selection: $time3, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station4)
- TextField("Please enter line name", text: $line4)
- DatePicker("Departure",selection: $time4, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station5)
- TextField("Please enter line name", text: $line5)
- DatePicker("Departure",selection: $time5, displayedComponents: .hourAndMinute)
- }
- Section(header: Text("Transfer")) {
- TextField("Please enter station name", text: $station6)
- TextField("Please enter line name", text: $line6)
- DatePicker("Departure",selection: $time6, displayedComponents: .hourAndMinute)
- }
- }
- Section(header: Text("Arriving")) {
- TextField("Please enter station name", text: $station7)
- DatePicker("Arriving at",selection: $time7, displayedComponents: .hourAndMinute)
- }
- Button(action: {
- let newMove = Move (context: viewContext)
- newMove.id = UUID()
- newMove.station = self.station
- newMove.line = self.line
- newMove.time = self.time
- newMove.station2 = self.station2
- newMove.line2 = self.line2
- newMove.time2 = self.time2
- newMove.station3 = self.station3
- newMove.line3 = self.line3
- newMove.time3 = self.time3
- newMove.station4 = self.station4
- newMove.line4 = self.line4
- newMove.time4 = self.time4
- newMove.station5 = self.station5
- newMove.line5 = self.line5
- newMove.time5 = self.time5
- newMove.station6 = self.station6
- newMove.line6 = self.line6
- newMove.time6 = self.time6
- newMove.station7 = self.station7
- newMove.time7 = self.time7
-
- do {
- try viewContext.save()
- presentationMode.wrappedValue.dismiss()
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- }, label: {
- Text("Save")
- })
- }
- }
- }
- else if self.categoryIndex == 3 {
- Form {
- Section(header: Text("Belongings")) {
- TextField("Please enter things you should bring", text: $belonging )
- }
- Button(action: {
- let newBelonging = Belonging (context: viewContext)
- newBelonging.belonging = self.belonging
- newBelonging.id = UUID()
- do {
- try viewContext.save()
- presentationMode.wrappedValue.dismiss()
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- }, label: {
- Text("Save")
- })
- }
- }
- else if self.categoryIndex == 4 {
- Form {
- Section(header: Text("Memo")) {
- TextField("Please make a memo", text:$memo )
- }
- Button(action: {
- let newMemo = Memo (context: viewContext)
- newMemo.memo = self.memo
- newMemo.id = UUID()
- do {
- try viewContext.save()
- presentationMode.wrappedValue.dismiss()
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- }, label: {
- Text("Save")
- })
- }
- }
- }
- }
- }
- // frame
- import SwiftUI
- struct todoFrame: View {
- var todoItem: Todo
- let todoDateFormat: DateFormatter = {
- let formatter = DateFormatter()
- formatter.timeStyle = .short
- return formatter
- }()
- var body: some View {
- VStack(alignment:.center) {
- Text(todoItem.todo!)
- .font(.system(size: 23))
- Divider()
- if todoItem.place != "" {
- Text("\(todoItem.place!)").font(.system(size: 15))
- }
- HStack {
- Text(" \(todoItem.start!, formatter: self.todoDateFormat)")
- Text("-")
- Text(" \(todoItem.end!, formatter: self.todoDateFormat)")
- }.font(.system(size: 15))
- if todoItem.cost != "" {
- Text("\(todoItem.cost!)").font(.system(size: 15))
- }
- }
- .frame(width: 200, height: 200)
- .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
- .cornerRadius(10)
- }
- }
- struct wantFrame: View {
- var wantItem: Want
- let wantDateFormat: DateFormatter = {
- let formatter = DateFormatter()
- formatter.timeStyle = .short
- return formatter
- }()
- var body: some View {
- VStack(alignment:.center) {
- Text(wantItem.want!)
- .font(.system(size: 23))
- Divider()
- if wantItem.place2 != "" {
- Text("\(wantItem.place2!)").font(.system(size: 15))
- }
- HStack {
- Text(" \(wantItem.start2!, formatter: self.wantDateFormat)")
- Text("-")
- Text(" \(wantItem.end2!, formatter: self.wantDateFormat)")
- }.font(.system(size: 15))
- if wantItem.cost2 != "" {
- Text("\(wantItem.cost2!)").font(.system(size: 15))
- }
- }.padding()
- .frame(width: 200, height: 200)
- .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
- .cornerRadius(10)
- }
- }
- struct moveFrame: View {
- var moveItem: Move
- let moveDateFormat: DateFormatter = {
- let formatter = DateFormatter()
- formatter.timeStyle = .short
- return formatter
- }()
-
- var body: some View {
- Group {
- Group {
- Text("\(moveItem.station!)(\(moveItem.line!))").font(.system(size: 23))
- Text("\(moveItem.time!, formatter: self.moveDateFormat)").font(.system(size: 15))
- Text("↓")
- }
- if moveItem.station2 != "" {
- Group {
- Text("\(moveItem.station2!)(\(moveItem.line2!))").font(.system(size: 23))
- Text("\(moveItem.time2!, formatter: self.moveDateFormat)").font(.system(size: 15))
- Text("↓")
- }
- }
- if moveItem.station3 != "" {
- Group {
- Text("\(moveItem.station3!)(\(moveItem.line3!))").font(.system(size: 23))
- Text(" \(moveItem.time3!, formatter: self.moveDateFormat)").font(.system(size: 15))
- Text("↓")
- }
- }
- if moveItem.station4 != "" {
- Group {
- Text("\(moveItem.station4!)(\(moveItem.line4!))").font(.system(size: 23))
- Text("\(moveItem.time4!, formatter: self.moveDateFormat)").font(.system(size: 15))
- Text("↓")
- }
- }
- if moveItem.station5 != "" {
- Group {
- Text("\(moveItem.station5!)(\(moveItem.line5!))").font(.system(size: 23))
- Text("\(moveItem.time5!, formatter: self.moveDateFormat)").font(.system(size: 15))
- Text("↓")
- }
- }
- if moveItem.station6 != "" {
- Group {
- Text("\(moveItem.station6!)(\(moveItem.line6!))").font(.system(size: 23))
- Text("\(moveItem.time6!, formatter: self.moveDateFormat)").font(.system(size: 15))
- Text("↓")
- }
- }
- Text("\(moveItem.station7!)").font(.system(size: 23))
- Text(" \(moveItem.time7!, formatter: self.moveDateFormat)").font(.system(size: 15))
- }
- .frame(width: 200, height: 200)
- .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
- .cornerRadius(10)
- }
- }
- struct belongingFrame: View {
- var belongingItem: Belonging
- var body: some View {
- Text(belongingItem.belonging!)
- .frame(width: 200, height: 200)
- .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
- .cornerRadius(10)
- }
- }
- struct memoFrame: View {
- var memoItem: Memo
- var body: some View {
- Text(memoItem.memo!)
- .frame(width: 200, height: 200)
- .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
- .cornerRadius(10)
- }
- }
- // Persistence
- import CoreData
- struct PersistenceController {
- static let shared = PersistenceController()
- let container: NSPersistentContainer
- init(inMemory: Bool = false) {
- container = NSPersistentContainer(name: "DesignGo")
- if inMemory {
- container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
- }
- container.loadPersistentStores(completionHandler: { (storeDescription, error) in
- if let error = error as NSError? {
- // Replace this implementation with code to handle the error appropriately.
- // 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.
- /*
- Typical reasons for an error here include:
- * The parent directory does not exist, cannot be created, or disallows writing.
- * The persistent store is not accessible, due to permissions or data protection when the device is locked.
- * The device is out of space.
- * The store could not be migrated to the current model version.
- Check the error message to determine what the actual problem was.
- */
- fatalError("Unresolved error \(error), \(error.userInfo)")
- }
- })
- }
- }
Digital Time Capsule
- // DesignMapApp
- import SwiftUI
- import CoreLocation
- @main
- struct DesignMapApp: App {
- let persistenceController = PersistenceController.shared
-
- var body: some Scene {
- WindowGroup {
- ContentView(locationSearchService: LocationSearchService())
- .environment(\.managedObjectContext, persistenceController.container.viewContext)
- }
- }
- }
- // ContentView
- import SwiftUI
- import CoreData
- import MapKit
- import CoreLocation
- import UIKit
- struct ContentView: View {
-
- @Environment(\.managedObjectContext) private var viewContext
- @FetchRequest(sortDescriptors: [])
- private var timeCapsules: FetchedResults<TimeCapsule>
-
-
- let geoCoder = CLGeocoder()
- @ObservedObject var locationSearchService: LocationSearchService
- @State var address = ""
- @State var addressCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 35.652832, longitude: 139.839478)
- @ObservedObject var locationManager = LocationManager()
- @State var showingSheet = false
- public static var add = false
- @State var showMessage = false
-
- var body: some View {
- NavigationView {
- ZStack {
- VStack {
- /*
- SearchBar(text: $locationSearchService.searchQuery)
- if locationSearchService.searchQuery != "" {
- List(locationSearchService.completions) { completion in
- Button(action: {
- address = completion.subtitle
- geoCoder.geocodeAddressString(address) { (placemarks, error) in
- guard
- let placemarks = placemarks,
- let location = placemarks.first?.location
- else {
- // handle no location found
- return
- }
- let coordinate = location.coordinate
- addressCoordinate = coordinate
- }
- }){
- VStack(alignment: .leading) {
- Text(completion.title)
- Text(completion.subtitle)
- .font(.subheadline)
- .foregroundColor(.gray)
- }
- }
- }
- }
- */
- ContentView.MapView(coordinate: CLLocationCoordinate2D(latitude: locationManager.lastLocation?.coordinate.latitude ?? 0, longitude: locationManager.lastLocation?.coordinate.longitude ?? 0))
- .edgesIgnoringSafeArea(/*@START_MENU_TOKEN@*/.all/*@END_MENU_TOKEN@*/)
-
- }
- /*
- GeometryReader { geometry in
- Text(address)
- .frame(width: 300, height: /*@START_MENU_TOKEN@*/100/*@END_MENU_TOKEN@*/, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
- .background(Color(red: 1, green: 1, blue: 1, opacity: 1))
- .cornerRadius(10)
- .position(x:geometry.frame(in: .global).maxX/2 , y:geometry.frame(in: .global).maxY-90)
- }
- */
-
- GeometryReader { geometry in
- Button(action:{
- self.showingSheet.toggle()
- }) {
- Circle()
- .frame(width: 50, height: 50)
- }.position(x:geometry.frame(in: .global).maxX-50 , y:geometry.frame(in: .global).maxY-170)
-
- NavigationLink(destination: TimeCapsuleList(), label: {
- Circle()
- .frame(width: 50, height: 50)
- })
- .position(x:geometry.frame(in: .global).maxX-50 , y:geometry.frame(in: .global).maxY-230)
-
- }
-
- GeometryReader { geometry in
- ForEach(timeCapsules){timeCapsule in
- if timeCapsule.latitude == locationManager.lastLocation?.coordinate.latitude && timeCapsule.longitude == locationManager.lastLocation?.coordinate.longitude &&
- timeCapsule.date! <= Date()
- {
- Button(action:{
- showMessage = true
- }){
- Text("Open")
- .fontWeight(.heavy)
- .foregroundColor(.white)
- .frame(width:200,height:50)
- .background(Color(red: 1, green: 0, blue: 0, opacity: 1))
- .cornerRadius(10)
- } .position(x:geometry.frame(in: .global).maxX/2 , y:geometry.frame(in: .global).maxY-170)
-
- if showMessage == true {
- Message(timeCapsule: timeCapsule)
- .position(x:geometry.frame(in: .global).maxX/2 , y:geometry.frame(in: .global).maxY-550)
- .gesture(
- TapGesture()
- .onEnded { _ in
- showMessage = false
- viewContext.delete(timeCapsule)
- try! viewContext.save()
- }
- )
- }
- }
- }
-
- }
- }.sheet(isPresented: $showingSheet) {
- settingSheet()
- }
- }
-
- }
-
-
-
- //Mapview------------------------------------------------------------------------------------
- struct MapView : UIViewRepresentable {
-
- let locationManager = CLLocationManager()
- var coordinate: CLLocationCoordinate2D
- let map = MKMapView()
- @ObservedObject var locationManager2 = LocationManager()
-
- @Environment(\.managedObjectContext) private var viewContext
- @FetchRequest(sortDescriptors: [])
- private var timeCapsules: FetchedResults<TimeCapsule>
-
- @FetchRequest(sortDescriptors: [])
- private var pins: FetchedResults<Pin>
-
-
- func makeUIView(context: UIViewRepresentableContext<MapView>) -> MKMapView {
-
- let coordinate = CLLocationCoordinate2D(latitude: locationManager2.lastLocation?.coordinate.latitude ?? 0, longitude: locationManager2.lastLocation?.coordinate.longitude ?? 0)
-
- map.region = MKCoordinateRegion(center: coordinate, latitudinalMeters: 50000, longitudinalMeters: 50000)
-
- for i in pins {
- let pinCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: i.pinLatitude ,longitude: i.pinLongitude)
- let pinAnnotaion = MKPointAnnotation()
- pinAnnotaion.coordinate = pinCoordinate
- map.addAnnotation(pinAnnotaion)
- }
-
-
-
- return map
- }
- func updateUIView(_ uiView: MKMapView, context: UIViewRepresentableContext<MapView>) {
- uiView.showsUserLocation = true
- locationManager.requestAlwaysAuthorization()
- locationManager.requestWhenInUseAuthorization()
-
- uiView.setCenter(coordinate, animated: true)
-
- let currentCoordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: locationManager2.lastLocation?.coordinate.latitude ?? 0, longitude: locationManager2.lastLocation?.coordinate.longitude ?? 0)
-
- let currentAnnotaion = MKPointAnnotation()
- currentAnnotaion.title = ""
- currentAnnotaion.subtitle = ""
-
-
- currentAnnotaion.coordinate = currentCoordinate
-
- if ContentView.add == true {
- uiView.addAnnotation(currentAnnotaion)}
-
- let newPin = Pin (context: viewContext)
- newPin.pinLatitude = locationManager2.lastLocation?.coordinate.latitude ?? 0
- newPin.pinLongitude = locationManager2.lastLocation?.coordinate.longitude ?? 0
-
- do {
- try viewContext.save()
- ContentView.add = true
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- }
- func makeCoordinator() -> Coordinator {
- return Coordinator(self)
- }
- class Coordinator: NSObject, MKMapViewDelegate, UIGestureRecognizerDelegate {
- var parent: MapView
- var gRecognizer = UITapGestureRecognizer()
- init(_ parent: MapView) {
- self.parent = parent
- super.init()
- self.gRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapHandler))
- self.gRecognizer.delegate = self
- self.parent.map.addGestureRecognizer(gRecognizer)
-
- }
-
- @objc func tapHandler(_ gesture: UITapGestureRecognizer) {
- let location = gRecognizer.location(in: self.parent.map)
- let coordinate = self.parent.map.convert(location, toCoordinateFrom: self.parent.map)
- self.parent.map.setCenter(coordinate, animated: true)
-
- }
- }
- }
- }
- struct Message: View {
-
- @Environment(\.managedObjectContext) private var viewContext
- var timeCapsule: TimeCapsule
- @ObservedObject var locationManager = LocationManager()
-
- var body: some View {
- Text(timeCapsule.message!)
- .frame(width: 300, height: 400)
- .background(Color(red: 1, green: 1, blue: 1))
- }
- }
- // TimecapsuleList
- import SwiftUI
- struct TimeCapsuleList: View {
-
- @Environment(\.managedObjectContext) private var viewContext
- @FetchRequest(sortDescriptors: [])
- private var timeCapsules: FetchedResults<TimeCapsule>
- let dateFormat: DateFormatter = {
- let formatter = DateFormatter()
- formatter.dateStyle = .medium
- return formatter
- }()
-
-
- var body: some View {
-
- VStack(){
- Text("Your Time Capsules List")
- .font(.title)
- List {
- ForEach(timeCapsules){timeCapsule in
- TimeCapsuleListFrame(timecapsule: timeCapsule)
- .contextMenu {
- Button(action:{
- withAnimation{
- viewContext.delete(timeCapsule)
- try! viewContext.save()
- }
- }, label: {
- Text("Delete")})
- }
- }
- }
- }
- }
- }
- struct TimeCapsuleListFrame : View {
-
- var timecapsule:TimeCapsule
- let dateFormat: DateFormatter = {
- let formatter = DateFormatter()
- formatter.dateStyle = .medium
- return formatter
- }()
- let date = Date()
-
- var body: some View {
- VStack(alignment:.leading){
- Text(timecapsule.place!)
- .font(.body)
- Text("( Buried on \(date,formatter: self.dateFormat), Available from \(timecapsule.date!, formatter: self.dateFormat))")
- .font(.caption)
- }
- }
- }
- // settingSheet
- import SwiftUI
- import CoreLocation
- struct settingSheet: View {
-
- @Environment (\.presentationMode) var presentationMode
- @FetchRequest(sortDescriptors: [])
- private var timeCapsules: FetchedResults<TimeCapsule>
-
- @State var date = Date()
- @State var message = ""
- @State var longitude: Double = 0
- @State var latitude: Double = 0
- @State var place = ""
-
-
- @ObservedObject var locationManager = LocationManager()
- @Environment(\.managedObjectContext) private var viewContext
-
- @State var showingAlert = false
-
-
- var body: some View {
-
- VStack{
- Form{
- Text("Message for future")
- TextEditor(text: $message)
- .foregroundColor(.black)
- .frame(width: 250, height: 200, alignment: .center)
-
- TextField("Place",text: $place)
- DatePicker("Days after...",selection: $date, displayedComponents: .date)
-
- Button(action:{
- let newTimeCapsule = TimeCapsule (context: viewContext)
- newTimeCapsule.message = self.message
- newTimeCapsule.id = UUID()
- newTimeCapsule.date = self.date
- newTimeCapsule.place = self.place
- newTimeCapsule.latitude = locationManager.lastLocation?.coordinate.latitude ?? 0
- newTimeCapsule.longitude = locationManager.lastLocation?.coordinate.longitude ?? 0
-
- do {
- try viewContext.save()
- ContentView.add = true
- } catch {
- let error = error as NSError
- fatalError("Unresolved Error: \(error)")
- }
- showingAlert = true
- }){
- Text("Save")
- }.alert(isPresented: $showingAlert) {
- Alert(title: Text("Complete"),
- message: Text("Your time capsule is buried. Please visit here after set time "),
- dismissButton: .default(Text("OK"),
- action: {
- ContentView.add = false
- presentationMode.wrappedValue.dismiss()
- }))
- }
- }
- }
- }
- }
- struct TextView: UIViewRepresentable {
- @Binding var text: String
- func makeCoordinator() -> Coordinator {
- Coordinator(self)
- }
- func makeUIView(context: Context) -> UITextView {
- let myTextView = UITextView()
- myTextView.delegate = context.coordinator
- myTextView.font = UIFont(name: "HelveticaNeue", size: 15)
- myTextView.isScrollEnabled = true
- myTextView.isEditable = true
- myTextView.isUserInteractionEnabled = true
- myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)
- return myTextView
- }
- func updateUIView(_ uiView: UITextView, context: Context) {
- uiView.text = text
- }
- class Coordinator : NSObject, UITextViewDelegate {
- var parent: TextView
- init(_ uiTextView: TextView) {
- self.parent = uiTextView
- }
- func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
- return true
- }
- func textViewDidChange(_ textView: UITextView) {
- print("text now: \(String(describing: textView.text!))")
- self.parent.text = textView.text
- }
- }
- }
- //LocationManager
- import Foundation
- import CoreLocation
- import Combine
- class LocationManager: NSObject, ObservableObject {
- override init() {
- super.init()
- self.locationManager.delegate = self
- self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
- self.locationManager.requestWhenInUseAuthorization()
- self.locationManager.startUpdatingLocation()
- }
- @Published var locationStatus: CLAuthorizationStatus? {
- willSet {
- objectWillChange.send()
- }
- }
- @Published var lastLocation: CLLocation? {
- willSet {
- objectWillChange.send()
- }
- }
- var statusString: String {
- guard let status = locationStatus else {
- return "unknown"
- }
- switch status {
- case .notDetermined: return "notDetermined"
- case .authorizedWhenInUse: return "authorizedWhenInUse"
- case .authorizedAlways: return "authorizedAlways"
- case .restricted: return "restricted"
- case .denied: return "denied"
- default: return "unknown"
- }
- }
- let objectWillChange = PassthroughSubject<Void, Never>()
- private let locationManager = CLLocationManager()
- }
- extension LocationManager: CLLocationManagerDelegate {
- func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
- self.locationStatus = status
- print(#function, statusString)
- }
- func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
- guard let location = locations.last else { return }
- self.lastLocation = location
- print(#function, location)
- }
- }
- // Persistence
- import CoreData
- struct PersistenceController {
- static let shared = PersistenceController()
-
- let container: NSPersistentContainer
- init(inMemory: Bool = false) {
- container = NSPersistentContainer(name: "DesignMap")
- if inMemory {
- container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
- }
- container.loadPersistentStores(completionHandler: { (storeDescription, error) in
- if let error = error as NSError? {
- // Replace this implementation with code to handle the error appropriately.
- // 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.
- /*
- Typical reasons for an error here include:
- * The parent directory does not exist, cannot be created, or disallows writing.
- * The persistent store is not accessible, due to permissions or data protection when the device is locked.
- * The device is out of space.
- * The store could not be migrated to the current model version.
- Check the error message to determine what the actual problem was.
- */
- fatalError("Unresolved error \(error), \(error.userInfo)")
- }
- })
- }
- }