ソースコード source code

下記アプリの主要なソースコードを公開しています。アプリ開発の参考になれば幸いです。

画像等が別途必要ですので下記情報のみでアプリが完成するものではありません。 アプリは少しずつ機能拡張していますのでストア公開されているアプリと内容が異なる場合があります。 コードはコピーして自由にお使いいただけます。ただし著作権は放棄しておりませんので全部の再掲載はご遠慮ください。部分的に再掲載したり、改変して再掲載するのは構いません。 自身のアプリ作成の参考として個人使用・商用問わず自由にお使いいただけます。 コード記述のお手本を示すものではありません。ミニアプリですので変数名などさほど気遣いしていない部分も有りますし間違いも有るかと思いますので参考程度にお考え下さい。 他の賢者の皆様が公開されているコードを参考にした箇所も含まれます。iOSアプリ開発の熟練者が書いたコードではありません。 エンジニア向け技術情報共有サービスではありませんので説明は省いています。ご了承ください。 GitHubなどへの公開は予定しておりません。

下記コードの最終ビルド日: 2021-05-03

BiorhythmApp.swift

//
//  BiorhythmApp.swift
//  Biorhythm
//
//  Created by akira ohmachi on 2021/04/11.
//

import SwiftUI
import UIKit
import GoogleMobileAds

// AppDelegateクラスを定義する
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

        // Mobile Ads SDKを初期化する
        GADMobileAds.sharedInstance().start(completionHandler: nil)
        
        return true
    }
}


@main
struct BiorhythmApp: App {
    // SwiftUI AppライフサイクルにAppDelegateクラスを注入する
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(PublicManager())
        }
    }
}

BirthView.swift

//
//  BirthView.swift
//  Biorhythm
//
//  Created by akira ohmachi on 2021/04/11.
//

import SwiftUI

struct BirthView: View {
    @EnvironmentObject var pub: PublicManager
    private let dateFormatter: DateFormatter = DateFormatter()
    @State private var pickDate: Date = Date()
    
    var body: some View {
        VStack() {
            HStack {
                Button(action: {
                    pub.isBirth = false
                }) {
                    HStack {
                        Image(systemName: "arrow.backward")
                        Text("Cancel")
                    }
                }
                Spacer()
                Button(action: {
                    let dateStr: String = self.dateFormatter.string(from: self.pickDate)
                    switch self.pub.selectedBirth {
                        case 1: self.pub.birth1 = dateStr
                        case 2: self.pub.birth2 = dateStr
                        case 3: self.pub.birth3 = dateStr
                        case 4: self.pub.birth4 = dateStr
                        case 5: self.pub.birth5 = dateStr
                        case 6: self.pub.birth6 = dateStr
                        default: break
                    }
                    self.pub.currentBirth = dateStr
                    self.pub.isBirth = false
                }) {
                    HStack {
                        Text("Apply")
                        Image(systemName: "checkmark.circle")
                    }
                }
            }
            .padding(20)
            Text("birth")
            DatePicker("", selection: self.$pickDate, displayedComponents: .date)
                .datePickerStyle(WheelDatePickerStyle())
                .labelsHidden()
            Spacer()
        }
        .onAppear {     //アプリ起動時に実行
            self.dateFormatter.dateFormat = "yyyy-MM-dd"
            self.pickDate = self.pub.tmpBirth
        }
        //.navigationBarTitle("Setting",displayMode: .automatic)
        //.navigationViewStyle(StackNavigationViewStyle())
        .navigationBarHidden(true)
    }
}

struct BirthView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            BirthView().environmentObject(PublicManager())
        }
    }
}

ConstValue.swift

//
//  ConstValue.swift
//  Biorhythm
//
//  Created by akira ohmachi on 2021/04/11.
//

import SwiftUI

class ConstValue: ObservableObject {

    //background color
    static let colorBg: Color = Color.init(red: 1, green: 1, blue: 1)

    //title color
    static let colorTitle: Color = Color.init(red: 101 / 255, green: 97 / 255, blue: 248 / 255)

    //button back color
    static let colorBirth1: Color = Color.init(red: 193 / 255, green:  83 / 255, blue: 248 / 255)
    static let colorBirth2: Color = Color.init(red: 167 / 255, green:  94 / 255, blue: 248 / 255)
    static let colorBirth3: Color = Color.init(red: 129 / 255, green:  89 / 255, blue: 248 / 255)
    static let colorBirth4: Color = Color.init(red: 100 / 255, green:  94 / 255, blue: 248 / 255)
    static let colorBirth5: Color = Color.init(red:  94 / 255, green: 123 / 255, blue: 249 / 255)
    static let colorBirth6: Color = Color.init(red:  90 / 255, green: 147 / 255, blue: 249 / 255)

    //button fore color
    static let buttonForeColor: Color = Color.init(red: 1, green: 1, blue: 1)
    static let buttonForeColorOn: Color = Color.init(red: 0, green: 0, blue: 0)

    //graph color
    static let colorGraphPlus: Color = Color.init(red: 0.95, green: 1, blue: 0.95)
    static let colorGraphMinus: Color = Color.init(red: 0.95, green: 0.95, blue: 1)

}

ContentView.swift

//
//  ContentView.swift
//  Biorhythm
//
//  Created by akira ohmachi on 2021/04/11.
//

import SwiftUI
import GoogleMobileAds

struct ContentView: View {
    @EnvironmentObject var pub: PublicManager
    @State private var destroyFlag: Bool = false
    @State private var buttonBirthHeightDiv: CGFloat = 14.0
    @State private var isInputBirth: Bool = false
    private let dateFormatter: DateFormatter = DateFormatter()
    private let dateFormatterGraph1: DateFormatter = DateFormatter()
    private let dateFormatterGraph2: DateFormatter = DateFormatter()
    private let graph2heightTimes: CGFloat = 10.0
    private let curveFineness1: Int = 200
    private let curveFineness2: Int = 1000
    @State private var lastSwipePosition: CGFloat = 0.0
    //
    var body: some View {
        NavigationView {
            GeometryReader { bodyView in
                VStack(spacing: 0) {
                    VStack(spacing: 0) {
                        Text("title")
                            .foregroundColor(Color.white)
                            .padding(5)
                    }
                    .frame(width:bodyView.size.width, alignment: .center)
                    .background(ConstValue.colorTitle)
                    Rectangle().fill(Color.white).frame(width: bodyView.size.width,height: 1)
                    VStack(spacing: 0) {
                        HStack(spacing: 0) {
                            Button(action:{
                                self.pub.selectedBirth = 1
                                self.selectedBirthColor()
                                self.pub.currentBirth = self.pub.birth1
                            }){
                                Text(self.pub.birth1)
                                    .frame(width:bodyView.size.width / 3 - 1, height: bodyView.size.height / self.buttonBirthHeightDiv, alignment: .center)
                                    .background(ConstValue.colorBirth1)
                                    .foregroundColor(self.pub.foreColorBirth1)
                            }
                            Rectangle().fill(Color.white).frame(width: 1, height: bodyView.size.height / self.buttonBirthHeightDiv)
                            Button(action:{
                                self.pub.selectedBirth = 2
                                self.selectedBirthColor()
                                self.pub.currentBirth = self.pub.birth2
                            }){
                                Text(self.pub.birth2)
                                    .frame(width:bodyView.size.width / 3, height: bodyView.size.height / self.buttonBirthHeightDiv, alignment: .center)
                                    .background(ConstValue.colorBirth2)
                                    .foregroundColor(self.pub.foreColorBirth2)
                            }
                            Rectangle().fill(Color.white).frame(width: 1, height: bodyView.size.height / self.buttonBirthHeightDiv)
                            Button(action:{
                                self.pub.selectedBirth = 3
                                self.selectedBirthColor()
                                self.pub.currentBirth = self.pub.birth3
                            }){
                                Text(self.pub.birth3)
                                    .frame(width:bodyView.size.width / 3 - 1, height: bodyView.size.height / self.buttonBirthHeightDiv, alignment: .center)
                                    .background(ConstValue.colorBirth3)
                                    .foregroundColor(self.pub.foreColorBirth3)
                            }
                        }
                    }
                    Rectangle().fill(Color.white).frame(width: bodyView.size.width,height: 1)
                    VStack(spacing: 0) {
                        HStack(spacing: 0) {
                            Button(action:{
                                self.pub.selectedBirth = 4
                                self.selectedBirthColor()
                                self.pub.currentBirth = self.pub.birth4
                            }){
                                Text(self.pub.birth4)
                                    .frame(width:bodyView.size.width / 3 - 1, height: bodyView.size.height / self.buttonBirthHeightDiv, alignment: .center)
                                    .background(ConstValue.colorBirth4)
                                    .foregroundColor(self.pub.foreColorBirth4)
                            }
                            Rectangle().fill(Color.white).frame(width: 1, height: bodyView.size.height / self.buttonBirthHeightDiv)
                            Button(action:{
                                self.pub.selectedBirth = 5
                                self.selectedBirthColor()
                                self.pub.currentBirth = self.pub.birth5
                            }){
                                Text(self.pub.birth5)
                                    .frame(width:bodyView.size.width / 3, height: bodyView.size.height / self.buttonBirthHeightDiv, alignment: .center)
                                    .background(ConstValue.colorBirth5)
                                    .foregroundColor(self.pub.foreColorBirth5)
                            }
                            Rectangle().fill(Color.white).frame(width: 1, height: bodyView.size.height / self.buttonBirthHeightDiv)
                            Button(action:{
                                self.pub.selectedBirth = 6
                                self.selectedBirthColor()
                                self.pub.currentBirth = self.pub.birth6
                            }){
                                Text(self.pub.birth6)
                                    .frame(width:bodyView.size.width / 3 - 1, height: bodyView.size.height / self.buttonBirthHeightDiv, alignment: .center)
                                    .background(ConstValue.colorBirth6)
                                    .foregroundColor(self.pub.foreColorBirth6)
                            }
                        }
                    }
                    Rectangle().fill(Color.white).frame(width: bodyView.size.width,height: 1)
                    ZStack(alignment: .bottom) {
                        ScrollView {
                            Spacer(minLength: 20.0)
                            VStack {
                                HStack {
                                    Text("birth")
                                        .frame(width:50, alignment: .leading)
                                    NavigationLink(destination: BirthView(),isActive: self.$pub.isBirth) {
                                        Button(action:{
                                            self.pub.tmpBirth = dateFormatter.date(from: self.pub.currentBirth) ?? Date()
                                            self.pub.isBirth = true
                                        }){
                                            Text(self.pub.currentBirth)
                                                .font(.largeTitle)
                                                .foregroundColor(Color.black)
                                        }
                                    }
                                    Image(systemName: "hand.tap")
                                        .foregroundColor(Color.gray)
                                }
                                .frame(width:bodyView.size.width, alignment: .center)
                                Spacer(minLength: 15.0)
                                HStack {
                                    Text("today")
                                        .frame(width:50, alignment: .leading)
                                    NavigationLink(destination: TodayView(),isActive: self.$pub.isToday) {
                                        Button(action:{
                                            self.pub.tmpToday = dateFormatter.date(from: self.pub.currentToday) ?? Date()
                                            self.pub.isToday = true
                                        }){
                                            Text(self.pub.currentToday)
                                                .font(.largeTitle)
                                                .foregroundColor(Color.black)
                                        }
                                    }
                                    Image(systemName: "hand.tap")
                                        .foregroundColor(Color.gray)
                                }
                                .frame(width:bodyView.size.width, alignment: .center)
                            }
                            ZStack {
                                Rectangle()
                                    .fill(ConstValue.colorBg)
                                    .frame(width: bodyView.size.width, height: bodyView.size.width * 0.6)
                                self.graph1a(width: bodyView.size.width)
                                self.graph1b(width: bodyView.size.width)
                            }
                            .gesture(DragGesture().onChanged(onChangedOn(value:)))
                            Text("physical")
                                .foregroundColor(Color.green)
                            Text("sensitivity")
                                .foregroundColor(Color.red)
                            Text("intellectual")
                                .foregroundColor(Color.blue)
                            Spacer(minLength: 20)
                            ZStack {
                                Rectangle()
                                    .fill(ConstValue.colorBg)
                                    .frame(width: bodyView.size.width, height: bodyView.size.width * self.graph2heightTimes)
                                self.graph2a(width: bodyView.size.width)
                                self.graph2b(width: bodyView.size.width)
                            }
                            Spacer(minLength: 150)
                        }
                        HStack(spacing: 0) {
                            Spacer(minLength: 0)
                            PublicManager.AdView().frame(maxWidth: bodyView.size.width, maxHeight: 50)
                            Spacer(minLength: 0)
                        }.background(Color(red:0.2,green:0.2,blue:0.2))
                    }
                }
                .background(ConstValue.colorBg)
                //.navigationBarTitle("")
                .navigationBarHidden(true)
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
        .onAppear {     //view起動時に実行
            self.dateFormatter.dateFormat = "yyyy-MM-dd"
            self.dateFormatterGraph1.dateFormat = "M/d"
            self.dateFormatterGraph2.dateFormat = "yyyy/MM/dd"
            self.selectedBirthColor()
            self.pub.currentToday = self.dateFormatter.string(from: Date())
        }
        .onDisappear {     //アプリ終了時
            self.destroyFlag = true
        }
    }
    
    private func onChangedOn(value: DragGesture.Value) {
        let offset = value.translation.width
        var addDay: Int = 0
        if self.lastSwipePosition + 10.0 < offset {
            self.lastSwipePosition = CGFloat(offset)
            addDay = -1
        } else if lastSwipePosition - 10.0 > offset {
            self.lastSwipePosition = CGFloat(offset)
            addDay = 1
        } else {
            return
        }
        let today: Date = dateFormatter.date(from: self.pub.currentToday) ?? Date()
        let today2 = Calendar.current.date(byAdding: .day, value: addDay, to: today)!
        self.pub.currentToday = self.dateFormatter.string(from: today2)
    }
    
    private func selectedBirthColor() {
        self.pub.foreColorBirth1 = ConstValue.buttonForeColor
        self.pub.foreColorBirth2 = ConstValue.buttonForeColor
        self.pub.foreColorBirth3 = ConstValue.buttonForeColor
        self.pub.foreColorBirth4 = ConstValue.buttonForeColor
        self.pub.foreColorBirth5 = ConstValue.buttonForeColor
        self.pub.foreColorBirth6 = ConstValue.buttonForeColor
        switch self.pub.selectedBirth {
            case 1: self.pub.foreColorBirth1 = ConstValue.buttonForeColorOn
            case 2: self.pub.foreColorBirth2 = ConstValue.buttonForeColorOn
            case 3: self.pub.foreColorBirth3 = ConstValue.buttonForeColorOn
            case 4: self.pub.foreColorBirth4 = ConstValue.buttonForeColorOn
            case 5: self.pub.foreColorBirth5 = ConstValue.buttonForeColorOn
            case 6: self.pub.foreColorBirth6 = ConstValue.buttonForeColorOn
            default: break
        }
        switch self.pub.selectedBirth {
            case 1: self.pub.currentBirth = self.pub.birth1
            case 2: self.pub.currentBirth = self.pub.birth2
            case 3: self.pub.currentBirth = self.pub.birth3
            case 4: self.pub.currentBirth = self.pub.birth4
            case 5: self.pub.currentBirth = self.pub.birth5
            case 6: self.pub.currentBirth = self.pub.birth6
            default: break
        }
    }
    
    private func graph1a(width: CGFloat) -> some View {
        let graphW: CGFloat = width * 0.96
        let graphH: CGFloat = width * 0.6 * 0.8
        func x(x: CGFloat) -> CGFloat {
            return x * graphW + (width * 0.02)
        }
        func y(y: CGFloat) -> CGFloat {
            return y * graphH + (width * 0.02)
        }
        let today: Date = dateFormatter.date(from: self.pub.currentToday) ?? Date()
        func text(addDay: Int) -> String {
            var dayComponent = DateComponents()
            dayComponent.day = addDay
            let theCalendar = Calendar.current
            let nextDate = theCalendar.date(byAdding: dayComponent, to: today)!
            //
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "M"
            let month = Int(dateFormatter.string(from: nextDate))!
            //
            return ((month < 10) ? "  " : "") + self.dateFormatterGraph1.string(from: nextDate)
        }
        var body: some View {
            ZStack {
                //プラスエリア
                Path { path in
                    path.move(to: CGPoint(x: x(x: 0.0), y: y(y: 0.0)))
                    path.addLines([
                        CGPoint(x: x(x: 1.0), y: y(y: 0.0)),
                        CGPoint(x: x(x: 1.0), y: y(y: 0.25)),
                        CGPoint(x: x(x: 0.0), y: y(y: 0.25)),
                        CGPoint(x: x(x: 0.0), y: y(y: 0.0))
                    ])
                }.fill(ConstValue.colorGraphPlus)
                //マイナスエリア
                Path { path in
                    path.move(to: CGPoint(x: x(x: 0.0), y: y(y: 0.75)))
                    path.addLines([
                        CGPoint(x: x(x: 1.0), y: y(y: 0.75)),
                        CGPoint(x: x(x: 1.0), y: y(y: 1.0)),
                        CGPoint(x: x(x: 0.0), y: y(y: 1.0)),
                        CGPoint(x: x(x: 0.0), y: y(y: 0.75))
                    ])
                }.fill(ConstValue.colorGraphMinus)
                //横 上
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.0), y: y(y: 0.0)),
                        CGPoint(x: x(x: 1.0), y: y(y: 0.0))
                    ])
                }.stroke(lineWidth: 1.0)
                .foregroundColor(Color.gray)
                //横 中
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.0), y: y(y: 0.5)),
                        CGPoint(x: x(x: 1.0), y: y(y: 0.5))
                    ])
                }.stroke(lineWidth: 1.0)
                .foregroundColor(Color.gray)
                //横 下
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.0), y: y(y: 1.0)),
                        CGPoint(x: x(x: 1.0), y: y(y: 1.0))
                    ])
                }.stroke(lineWidth: 1.0)
                .foregroundColor(Color.gray)
                //横 25%
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.0), y: y(y: 0.25)),
                        CGPoint(x: x(x: 1.0), y: y(y: 0.25))
                    ])
                }.stroke(style:StrokeStyle(dash:[3]))
                .foregroundColor(Color.gray)
                //横 75%
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.0), y: y(y: 0.75)),
                        CGPoint(x: x(x: 1.0), y: y(y: 0.75))
                    ])
                }.stroke(style:StrokeStyle(dash:[3]))
                .foregroundColor(Color.gray)
                //縦
                ForEach(0..<41) { num in
                    if (num + 1) % 4 == 0 {
                        Path { path in
                            path.addLines([
                                CGPoint(x: x(x: CGFloat(num) / 40.0), y: y(y: 0.0)),
                                CGPoint(x: x(x: CGFloat(num) / 40.0), y: y(y: 1.05))
                            ])
                        }.stroke(lineWidth: 1.0)
                        .foregroundColor(Color.black)
                    } else {
                        Path { path in
                            path.addLines([
                                CGPoint(x: x(x: CGFloat(num) / 40.0), y: y(y: 0.0)),
                                CGPoint(x: x(x: CGFloat(num) / 40.0), y: y(y: 1.0))
                            ])
                        }.stroke(lineWidth: 1.0)
                        .foregroundColor(Color.gray)
                    }
                }
                //文字
                ForEach(0..<41) { num in
                    if (num + 1) % 4 == 0 {
                        Text(text(addDay: num - 3))
                            .font(.caption2)
                            .foregroundColor(Color.black)
                            .frame(width: graphW, height: graphH, alignment: .topLeading)
                            .offset(x: x(x: CGFloat(num) / 40.0 - 0.06), y: y(y: 0.95))
                    }
                }
            }
        }
        return body
    }

    private func graph1b(width: CGFloat) -> some View {
        let graphW: CGFloat = width * 0.96
        let graphH: CGFloat = width * 0.6 * 0.8
        func x(x: CGFloat) -> CGFloat {
            return x * graphW + (width * 0.02)
        }
        func y(y: CGFloat) -> CGFloat {
            return y * graphH + (width * 0.02)
        }
        func degSin(degrees: Double) -> Double {
            return __sinpi(degrees / 180.0)
        }
        let birth: Date = dateFormatter.date(from: self.pub.currentBirth) ?? Date()
        let today: Date = dateFormatter.date(from: self.pub.currentToday) ?? Date()
        let diff: Int = Calendar.current.dateComponents([.day], from: birth, to: today).day ?? 0
        let bioP: Double = Double(diff % 23)
        let bioS: Double = Double(diff % 28)
        let bioI: Double = Double(diff % 33)
        var bioPAry: Array<Double> = []
        var bioSAry: Array<Double> = []
        var bioIAry: Array<Double> = []
        for i in 0...self.curveFineness1 {
            let oneDay: Double = Double(i) / (Double(self.curveFineness1) / 40.0)
            bioPAry.append(degSin(degrees: (bioP + oneDay - 3) * 360.0 / 23.0) * -1)
            bioSAry.append(degSin(degrees: (bioS + oneDay - 3) * 360.0 / 28.0) * -1)
            bioIAry.append(degSin(degrees: (bioI + oneDay - 3) * 360.0 / 33.0) * -1)
        }
        var body: some View {
            ZStack {
                ForEach(1..<bioPAry.count) { num in
                    Path { path in
                        path.addLines([
                            CGPoint(x: x(x: CGFloat(num - 1) / CGFloat(self.curveFineness1)), y: y(y: CGFloat((bioPAry[num - 1] + 1) / 2))),
                            CGPoint(x: x(x: CGFloat(num) / CGFloat(self.curveFineness1)), y: y(y: CGFloat((bioPAry[num] + 1) / 2)))
                        ])
                    }.stroke(lineWidth: 1.5)
                }
                .foregroundColor(Color.green)
                ForEach(1..<bioPAry.count) { num in
                    Path { path in
                        path.addLines([
                            CGPoint(x: x(x: CGFloat(num - 1) / CGFloat(self.curveFineness1)), y: y(y: CGFloat((bioSAry[num - 1] + 1) / 2))),
                            CGPoint(x: x(x: CGFloat(num) / CGFloat(self.curveFineness1)), y: y(y: CGFloat((bioSAry[num] + 1) / 2)))
                        ])
                    }.stroke(lineWidth: 1.5)
                }
                .foregroundColor(Color.red)
                ForEach(1..<bioPAry.count) { num in
                    Path { path in
                        path.addLines([
                            CGPoint(x: x(x: CGFloat(num - 1) / CGFloat(self.curveFineness1)), y: y(y: CGFloat((bioIAry[num - 1] + 1) / 2))),
                            CGPoint(x: x(x: CGFloat(num) / CGFloat(self.curveFineness1)), y: y(y: CGFloat((bioIAry[num] + 1) / 2)))
                        ])
                    }.stroke(lineWidth: 1.5)
                }
                .foregroundColor(Color.blue)
            }
        }
        return body
    }

    //縦のグラフ
    private func graph2a(width: CGFloat) -> some View {
        let graphW: CGFloat = width * 0.7
        let graphH: CGFloat = width * self.graph2heightTimes
        func x(x: CGFloat) -> CGFloat {
            return x * graphW + (width * 0.26)
        }
        func y(y: CGFloat) -> CGFloat {
            return y * graphH + (width * 0.02)
        }
        let today: Date = dateFormatter.date(from: self.pub.currentToday) ?? Date()
        func text(addDay: Int) -> String {
            var dayComponent = DateComponents()
            dayComponent.day = addDay
            let theCalendar = Calendar.current
            let nextDate = theCalendar.date(byAdding: dayComponent, to: today)!
            return self.dateFormatterGraph2.string(from: nextDate)
        }
        var body: some View {
            ZStack {
                //縦 プラスエリア
                Path { path in
                    path.move(to: CGPoint(x: x(x: 0.75), y: y(y: 0.0)))
                    path.addLines([
                        CGPoint(x: x(x: 1.0), y: y(y: 0.0)),
                        CGPoint(x: x(x: 1.0), y: y(y: 1.0)),
                        CGPoint(x: x(x: 0.75), y: y(y: 1.0)),
                        CGPoint(x: x(x: 0.75), y: y(y: 0.0))
                    ])
                }.fill(ConstValue.colorGraphPlus)
                //縦 マイナスエリア
                Path { path in
                    path.move(to: CGPoint(x: x(x: 0.0), y: y(y: 0.0)))
                    path.addLines([
                        CGPoint(x: x(x: 0.25), y: y(y: 0.0)),
                        CGPoint(x: x(x: 0.25), y: y(y: 1.0)),
                        CGPoint(x: x(x: 0.0), y: y(y: 1.0)),
                        CGPoint(x: x(x: 0.0), y: y(y: 0.0))
                    ])
                }.fill(ConstValue.colorGraphMinus)
                //縦 右
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 1.0), y: y(y: 0.0)),
                        CGPoint(x: x(x: 1.0), y: y(y: 1.0))
                    ])
                }.stroke(lineWidth: 1.0)
                .foregroundColor(Color.gray)
                //縦 中
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.5), y: y(y: 0.0)),
                        CGPoint(x: x(x: 0.5), y: y(y: 1.0))
                    ])
                }.stroke(lineWidth: 1.0)
                .foregroundColor(Color.gray)
                //縦 左
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.0), y: y(y: 0.0)),
                        CGPoint(x: x(x: 0.0), y: y(y: 1.0))
                    ])
                }.stroke(lineWidth: 1.0)
                .foregroundColor(Color.gray)
                //縦 75%
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.75), y: y(y: 0.0)),
                        CGPoint(x: x(x: 0.75), y: y(y: 1.0))
                    ])
                }.stroke(style:StrokeStyle(dash:[3]))
                .foregroundColor(Color.gray)
                //縦 25%
                Path { path in
                    path.addLines([
                        CGPoint(x: x(x: 0.25), y: y(y: 0.0)),
                        CGPoint(x: x(x: 0.25), y: y(y: 1.0))
                    ])
                }.stroke(style:StrokeStyle(dash:[3]))
                .foregroundColor(Color.gray)
                //横
                ForEach(0..<366) { num in
                    if (num + 1) % 4 == 0 {
                        Path { path in
                            path.addLines([
                                CGPoint(x: x(x: -0.05), y: y(y: CGFloat(num) / 365.0)),
                                CGPoint(x: x(x: 1.0), y: y(y: CGFloat(num) / 365.0))
                            ])
                        }.stroke(lineWidth: 1.0)
                        .foregroundColor(Color.black)
                    } else {
                        Path { path in
                            path.addLines([
                                CGPoint(x: x(x: 0.0), y: y(y: CGFloat(num) / 365.0)),
                                CGPoint(x: x(x: 1.0), y: y(y: CGFloat(num) / 365.0))
                            ])
                        }.stroke(lineWidth: 1.0)
                        .foregroundColor(Color.gray)
                    }
                }
                //文字
                ForEach(0..<366) { num in
                    if (num + 1) % 4 == 0 {
                        Text(text(addDay: num - 3))
                            .font(.caption2)
                            .foregroundColor(Color.black)
                            .frame(width: width, height: graphH, alignment: .topLeading)
                            .offset(x: 5.2, y: y(y: CGFloat(num) / 365.0) - 5.8)
                    }
                }
            }
        }
        return body
    }

    //縦のグラフ
    private func graph2b(width: CGFloat) -> some View {
        let graphW: CGFloat = width * 0.7
        let graphH: CGFloat = width * self.graph2heightTimes
        func x(x: CGFloat) -> CGFloat {
            return x * graphW + (width * 0.26)
        }
        func y(y: CGFloat) -> CGFloat {
            return y * graphH + (width * 0.02)
        }
        func degSin(degrees: Double) -> Double {
            return __sinpi(degrees / 180.0)
        }
        let birth: Date = dateFormatter.date(from: self.pub.currentBirth) ?? Date()
        let today: Date = dateFormatter.date(from: self.pub.currentToday) ?? Date()
        let diff: Int = Calendar.current.dateComponents([.day], from: birth, to: today).day ?? 0
        let bioP: Double = Double(diff % 23)
        let bioS: Double = Double(diff % 28)
        let bioI: Double = Double(diff % 33)
        var bioPAry: Array<Double> = []
        var bioSAry: Array<Double> = []
        var bioIAry: Array<Double> = []
        for i in 0...self.curveFineness2 {
            let oneDay: Double = Double(i) / (Double(self.curveFineness2) / 365.0)
            bioPAry.append(degSin(degrees: (bioP + oneDay - 3) * 360.0 / 23.0))
            bioSAry.append(degSin(degrees: (bioS + oneDay - 3) * 360.0 / 28.0))
            bioIAry.append(degSin(degrees: (bioI + oneDay - 3) * 360.0 / 33.0))
        }
        var body: some View {
            ZStack {
                ForEach(1..<bioPAry.count) { num in
                    Path { path in
                        path.addLines([
                            CGPoint(x: x(x: CGFloat((bioPAry[num - 1] + 1) / 2)), y: y(y: CGFloat(num - 1) / CGFloat(self.curveFineness2))),
                            CGPoint(x: x(x: CGFloat((bioPAry[num] + 1) / 2)), y: y(y: CGFloat(num) / CGFloat(self.curveFineness2)))
                        ])
                    }.stroke(lineWidth: 1.5)
                }
                .foregroundColor(Color.green)
                ForEach(1..<bioPAry.count) { num in
                    Path { path in
                        path.addLines([
                            CGPoint(x: x(x: CGFloat((bioSAry[num - 1] + 1) / 2)), y: y(y: CGFloat(num - 1) / CGFloat(self.curveFineness2))),
                            CGPoint(x: x(x: CGFloat((bioSAry[num] + 1) / 2)), y: y(y: CGFloat(num) / CGFloat(self.curveFineness2)))
                        ])
                    }.stroke(lineWidth: 1.5)
                }
                .foregroundColor(Color.red)
                ForEach(1..<bioPAry.count) { num in
                    Path { path in
                        path.addLines([
                            CGPoint(x: x(x: CGFloat((bioIAry[num - 1] + 1) / 2)), y: y(y: CGFloat(num - 1) / CGFloat(self.curveFineness2))),
                            CGPoint(x: x(x: CGFloat((bioIAry[num] + 1) / 2)), y: y(y: CGFloat(num) / CGFloat(self.curveFineness2)))
                        ])
                    }.stroke(lineWidth: 1.5)
                }
                .foregroundColor(Color.blue)
            }
        }
        return body
    }
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView().environmentObject(PublicManager())
        }
    }
}

PublicManager.swift

//
//  PublicManager.swift
//  Biorhythm
//
//  Created by akira ohmachi on 2021/04/11.
//

import SwiftUI
import GoogleMobileAds

class PublicManager: ObservableObject {
    
    @AppStorage("birth1") var birth1: String = "2000-01-01"
    @AppStorage("birth2") var birth2: String = "2000-01-01"
    @AppStorage("birth3") var birth3: String = "2000-01-01"
    @AppStorage("birth4") var birth4: String = "2000-01-01"
    @AppStorage("birth5") var birth5: String = "2000-01-01"
    @AppStorage("birth6") var birth6: String = "2000-01-01"
    @AppStorage("selectedBirth") var selectedBirth: Int = 1

    @Published var isBirth: Bool = false
    @Published var isToday: Bool = false
    
    @Published var tmpBirth = Date()
    @Published var tmpToday = Date()
    @Published var currentBirth: String = "2000-01-01"
    @Published var currentToday: String = "2020-01-01"

    @Published var foreColorBirth1: Color = ConstValue.buttonForeColor
    @Published var foreColorBirth2: Color = ConstValue.buttonForeColor
    @Published var foreColorBirth3: Color = ConstValue.buttonForeColor
    @Published var foreColorBirth4: Color = ConstValue.buttonForeColor
    @Published var foreColorBirth5: Color = ConstValue.buttonForeColor
    @Published var foreColorBirth6: Color = ConstValue.buttonForeColor


    //--------------------------------------------------
    //adMob
    
    struct AdView: UIViewRepresentable {
        func makeUIView(context: Context) -> GADBannerView {
            let banner = GADBannerView(adSize: kGADAdSizeBanner)
            #if DEBUG
            banner.adUnitID = "ca-app-pub-3940256099942544/2934735716"
            #else
            banner.adUnitID = "ca-app-pub-0000000000000000/0000000000"
            #endif
            banner.rootViewController = UIApplication.shared.windows.first?.rootViewController
            banner.load(GADRequest())
            return banner
        }

        func updateUIView(_ uiView: GADBannerView, context: Context) {
        }
    }

    //--------------------------------------------------

}

TodayView.swift

//
//  TodayView.swift
//  Biorhythm
//
//  Created by akira ohmachi on 2021/04/11.
//

import SwiftUI

struct TodayView: View {
    @EnvironmentObject var pub: PublicManager
    private let dateFormatter: DateFormatter = DateFormatter()
    @State private var pickDate: Date = Date()
    
    var body: some View {
        VStack() {
            HStack {
                Button(action: {
                    pub.isToday = false
                }) {
                    HStack {
                        Image(systemName: "arrow.backward")
                        Text("Cancel")
                    }
                }
                Spacer()
                Button(action: {
                    self.pub.currentToday = self.dateFormatter.string(from: self.pickDate)
                    self.pub.isToday = false
                }) {
                    HStack {
                        Text("Apply")
                        Image(systemName: "checkmark.circle")
                    }
                }
            }
            .padding(20)
            Text("today")
            DatePicker("", selection: self.$pickDate, displayedComponents: .date)
                .datePickerStyle(WheelDatePickerStyle())
                .labelsHidden()
            Spacer()
        }
        .onAppear {     //アプリ起動時に実行
            self.dateFormatter.dateFormat = "yyyy-MM-dd"
            self.pickDate = self.pub.tmpToday
        }
        //.navigationBarTitle("Setting",displayMode: .automatic)
        //.navigationViewStyle(StackNavigationViewStyle())
        .navigationBarHidden(true)
    }
}

struct TodayView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            TodayView().environmentObject(PublicManager())
        }
    }
}