ソースコード source code

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

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

下記コードの最終ビルド日: 2021-04-23

ConstValue.swift

//
//  ConstValue.swift
//  WhichIsBetterValue
//
//  Created by akira ohmachi on 2021/04/10.
//

import SwiftUI

class ConstValue: ObservableObject {

    //background
    static let colorBg: Color = Color.init(red:0.9,green:0.9,blue:0.8)
    
    //button color
    static let colorStart: Color = Color.init(red:0.238, green:0.77, blue:0.387)
    static let colorSetting: Color = Color.init(red:0.543, green:0.77, blue:0.289)
    
    static let colorA: Color = Color.init(red:0.5, green:0.5, blue:1.0, opacity: 0.7)
    static let colorB: Color = Color.init(red:1.0, green:0.5, blue:0.5, opacity: 0.7)
    
    static let sideWidthRatio: CGFloat = 0.05
    static let centerWidthRatio: CGFloat = 0.3
    
}

ContentView.swift

//
//  ContentView.swift
//  WhichIsBetterValue
//
//  Created by akira ohmachi on 2021/04/10.
//

import SwiftUI
import GoogleMobileAds

struct ContentView: View {
    @EnvironmentObject var pub: PublicManager
    @State private var destroyFlag: Bool = false
    @State private var isClearAlert: Bool = false
    @State private var unitPrice1: String = ""
    @State private var unitPrice2: String = ""
    @State private var resultImage: String = "cat_0"
    private var resultImage0: String = "cat_0"
    private var resultImageA: String = "cat_a"
    private var resultImageB: String = "cat_b"
    //
    var body: some View {
        NavigationView {
            GeometryReader { bodyView in
                VStack(spacing: 0) {
                    HStack(spacing: 0) {
                        Text("title")
                            .frame(width:bodyView.size.width / 4 * 3, height: bodyView.size.height / 10, alignment: .center)
                            .background(ConstValue.colorStart)
                            .foregroundColor(Color.white)
                        Rectangle().fill(Color.white).frame(width: 1,height: bodyView.size.height / 10)
                        Button(action:{
                            self.isClearAlert = true
                        }){
                            Text("clear")
                                .frame(width:bodyView.size.width / 4, height: bodyView.size.height / 10, alignment: .center)
                                .background(ConstValue.colorSetting)
                                .foregroundColor(Color.white)
                        }.alert(isPresented: self.$isClearAlert, content: self.clearAlert)
                    }
                    .frame(width:bodyView.size.width, height:bodyView.size.height / 10)
                    Rectangle().fill(Color.white).frame(width: bodyView.size.width,height: 1)
                    ZStack(alignment: .bottom) {
                        ScrollView {
                            Spacer(minLength: 15.0)
                            HStack {
                                Spacer()
                                VStack(spacing: 0) {
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Text("A")
                                                .foregroundColor(Color.white)
                                        }
                                    }
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Spacer()
                                            Text("net")
                                                .foregroundColor(Color.white)
                                            Spacer()
                                        }
                                    }
                                    HStack(spacing: 0) {
                                        Spacer()
                                        TextField("", text: Binding(
                                                get: {self.pub.net1},
                                                set: {self.pub.net1 = $0.filter{".0123456789".contains($0)}})
                                            ,onEditingChanged: {_ in
                                                self.calc()
                                            }, onCommit: {
                                                //self.calc()
                                            })
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .keyboardType(.decimalPad)
                                        Spacer()
                                    }
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Spacer()
                                            Text("price")
                                                .foregroundColor(Color.white)
                                            Spacer()
                                        }
                                    }
                                    HStack(spacing: 0) {
                                        Spacer()
                                        TextField("", text: Binding(
                                                get: {self.pub.price1},
                                                set: {self.pub.price1 = $0.filter{".0123456789".contains($0)}})
                                            ,onEditingChanged: {_ in
                                                self.calc()
                                            }, onCommit: {
                                                //self.calc()
                                            })
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .keyboardType(.decimalPad)
                                        Spacer()
                                    }
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Spacer()
                                            Text("unitPrice")
                                                .foregroundColor(Color.white)
                                            Spacer()
                                        }
                                    }
                                    HStack(spacing: 0) {
                                        Spacer()
                                        Text(self.unitPrice1)
                                        Spacer()
                                    }
                                    Spacer(minLength: 30.0)
                                }.frame(minWidth: bodyView.size.width * (ConstValue.centerWidthRatio + (ConstValue.sideWidthRatio * 2)))
                                .background(ConstValue.colorA)
                                .cornerRadius(bodyView.size.width * ConstValue.sideWidthRatio)
                                Spacer()
                                VStack(spacing: 0) {
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Text("B")
                                                .foregroundColor(Color.white)
                                        }
                                    }
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Spacer()
                                            Text("net")
                                                .foregroundColor(Color.white)
                                            Spacer()
                                        }
                                    }
                                    HStack(spacing: 0) {
                                        Spacer()
                                        TextField("", text: Binding(
                                                get: {self.pub.net2},
                                                set: {self.pub.net2 = $0.filter{".0123456789".contains($0)}})
                                            ,onEditingChanged: {_ in
                                                self.calc()
                                            }, onCommit: {
                                                //self.calc()
                                            })
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .keyboardType(.decimalPad)
                                        Spacer()
                                    }
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Spacer()
                                            Text("price")
                                                .foregroundColor(Color.white)
                                            Spacer()
                                        }
                                    }
                                    HStack(spacing: 0) {
                                        Spacer()
                                        TextField("", text: Binding(
                                                get: {self.pub.price2},
                                                set: {self.pub.price2 = $0.filter{".0123456789".contains($0)}})
                                            ,onEditingChanged: {_ in
                                                self.calc()
                                            }, onCommit: {
                                                //self.calc()
                                            })
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .keyboardType(.decimalPad)
                                        Spacer()
                                    }
                                    VStack {
                                        Spacer()
                                        HStack(spacing: 0) {
                                            Spacer()
                                            Text("unitPrice")
                                                .foregroundColor(Color.white)
                                            Spacer()
                                        }
                                    }
                                    HStack(spacing: 0) {
                                        Spacer()
                                        Text(self.unitPrice2)
                                        Spacer()
                                    }
                                    Spacer(minLength: 30.0)
                                }.frame(minWidth: bodyView.size.width * (ConstValue.centerWidthRatio + (ConstValue.sideWidthRatio * 2)))
                                .background(ConstValue.colorB)
                                .cornerRadius(bodyView.size.width * ConstValue.sideWidthRatio)
                                Spacer()
                            }
                            Spacer()
                            Image(self.resultImage).resizable()
                                .frame(width: bodyView.size.width * 0.5, height: bodyView.size.width * 0.5 * 0.732)

                            Spacer(minLength: 150)
                        }
                        .onTapGesture {     //背景タップでキーボードを閉じる
                            UIApplication.shared.closeKeyboard()
                        }
                        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 {     //アプリ起動時に実行
        }
        .onDisappear {     //アプリ終了時
            self.destroyFlag = true
        }
    }
    
    private func clearAlert() -> Alert {
        return Alert(title: Text("clearTitle"),
                 message: Text("clearMessage"),
                 primaryButton: .cancel(Text("cancel")),
                 secondaryButton: .destructive(
                    Text("clear"),
                    action: self.clearValue
                 )
            )
    }
    
    private func clearValue() {
        self.pub.net1 = ""
        self.pub.price1 = ""
        self.pub.net2 = ""
        self.pub.price2 = ""
        self.unitPrice1 = ""
        self.unitPrice2 = ""
        self.resultImage = self.resultImage0
    }
    
    private func calc() {
        //print(self.pub.net1)  //test
        let n1 = self.strToFloat(str: self.pub.net1)
        self.pub.net1 = self.floatToMinStr(num: n1)
        let n2 = self.strToFloat(str: self.pub.net2)
        self.pub.net2 = self.floatToMinStr(num: n2)
        let p1 = self.strToFloat(str: self.pub.price1)
        self.pub.price1 = self.floatToMinStr(num: p1)
        let p2 = self.strToFloat(str: self.pub.price2)
        self.pub.price2 = self.floatToMinStr(num: p2)
        var unit1: Float = 0.0
        var unit2: Float = 0.0
        if n1 != 0 {
            unit1 = p1 / n1
            self.unitPrice1 = String(format: "%.2f",unit1)
        } else {
            self.unitPrice1 = ""
        }
        if n2 != 0 {
            unit2 = p2 / n2
            self.unitPrice2 = String(format: "%.2f",unit2)
        } else {
            self.unitPrice2 = ""
        }
        if unit1 < unit2 && unit1 != 0 {
            self.resultImage = self.resultImageA
        } else if unit1 > unit2 && unit2 != 0 {
            self.resultImage = self.resultImageB
        } else {
            self.resultImage = self.resultImage0
        }
    }
    
    private func strToFloat(str: String) -> Float {
        var str2: String = ""
        var periodFlag: Bool = false
        for ch in str {
            if ["0","1","2","3","4","5","6","7","8","9","."].contains(ch) {
                if ch != "." {
                    str2 += String(ch)
                } else if ch == "." && periodFlag == false {
                    str2 += String(ch)
                    periodFlag = true
                }
            }
        }
        return Float("0" + str2)!
    }

    private func floatToMinStr(num: Float) -> String {
        if num == 0.0 {
            return ""
        }
        if num == Float(Int(num)) {
            return String(Int(num))
        }
        return String(num)
    }

}

extension UIApplication {
    func closeKeyboard() {  //キーボードを閉じる
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

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

PublicManager.swift

//
//  PublicManager.swift
//  WhichIsBetterValue
//
//  Created by akira ohmachi on 2021/04/10.
//

import SwiftUI
import GoogleMobileAds

class PublicManager: ObservableObject {
    
    @AppStorage("net1") var net1: String = ""
    @AppStorage("price1") var price1: String = ""
    @AppStorage("net2") var net2: String = ""
    @AppStorage("price2") var price2: String = ""
 
    //--------------------------------------------------
    //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) {
        }
    }

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

}

WhichIsBetterValueApp.swift

//
//  WhichIsBetterValueApp.swift
//  WhichIsBetterValue
//
//  Created by akira ohmachi on 2021/04/10.
//

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 WhichIsBetterValueApp: App {
    // SwiftUI AppライフサイクルにAppDelegateクラスを注入する
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

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