血圧管理カレンダー(Swift)

血圧管理カレンダー

macOS Mojava 10.14.6 / Xcode 11.3.1 / Swift 5.0
カレンダーに血圧を入力して健康管理に役立ててみる。
画像をクリックすると動画が表示されます。

血圧の入力

日付を選択し(青い枠線で囲まれる)入力ボタンを押す、または日付をダブルクリックすれば、その日の血圧入力シートが開く。
キーボード、または血圧入力シートの数字ボタンをクリックして血圧を入力する。確定フラグをオンにし登録ボタンを実行すると血圧データはデータベースに登録される。入力済みの日は日付が丸印で囲まれる。確定フラグをオフで登録した場合は、データは登録されるが、入力未完了というステータスになる。

血圧一覧表の表示

一覧表示ボタンをクリックして、その月の血圧の一覧表を表示する。日毎の血圧値は横向きの棒グラフで表す。基準値を超えた高血圧の場合、値とグラフの色を変える。
血圧一覧表のビュー構造
[月間血圧一覧表]

処理方式

クライアント/サーバ方式とする。アプリケーションからサーバにHTTPリクエストを送り、サーバはJSON形式のレスポンスデータを返す。データベースはMySQLで実装し、PHPスクリプトでデータの参照・更新を行う。
Webサーバー:Apache2.4 & PHP5.6
データベース:MySQL5.7

クラス仕様

本機能は シンプルカレンダー をベースに、血圧の入力機能と一覧表の表示機能を追加する。
血圧データを保存するデータベースはサーバにおく。本アプリケーションは、入力された血圧データをデータベースに登録し、データベースから特定の期間の血圧データを取得するという処理を HTTP通信により行う。本稿では、HTTPリクエスト/レスポンスのインタフェースだけ示し、サーバ側の処理方式については記述しない。
実装の方針としては、クラスの継承を検討し、既存クラスを修正するとしても、既存部分の変更は極力避け、機能の単純な追加になるよう努める。
シンプルカレンダーの UACalendarクラス、UACalendarDateクラス、UADateUtilクラスは、日付やカレンダーに関する汎用的なクラスなので、そのまま使用する。
血圧管理カレンダーとシンプルカレンダーの表示上の違いは、カレンダーの下に入力ボタンと一覧表示ボタンが追加されることと、日付の表示で血圧を入力した日に入力済みの丸印が付くことだけである。
したがって、カレンダーの表示を制御する UAViewクラス、および日付の表示を制御する UAItemViewクラスはサブクラス化し、追加機能はサブクラスに実装できそうである。
本アプリケーションでは、カレンダーの表示を制御する UAHealthViewクラスは UAViewクラスを継承した。一方、日付の表示を制御する UAItemViewクラスは、サブクラス化せず、修正して必要な機能を追加した。
なぜサブクラス化できないかというと、UAItemViewクラスはサブクラス化によりクラス名が変わる。UAItemViewクラスを利用する UAViewクラスはクラス名を指定してオブジェクトを作成しているが、クラス名が変わった場合、この部分の記述も変えなくてはいけない。しかし、UAViewクラスは UAHealthViewクラスの継承元なので変更することはできないということである。(それをしたら継承の意味がなくなってしまう)
[クラス構造図]

class UAHealthView: UAView

血圧管理カレンダーを表示する。シンプルカレンダーの UAViewクラスを継承する。
func arrangeControlViews2( )
血圧入力シート、血圧一覧表を開くボタンを作成する。イニシャライザから呼ばれる。
override func putDateToIemView( )
UAViewクラスの同メソッドをオーバーライドする。
サーバから1ヶ月分の血圧データを取得し、それぞれの日付ビューのプロパティに血圧データをセットする。
func clickOpen( )
血圧入力シートを開く。
func clickDisplay( )
血圧一覧表を作成して開く。

class UAItemView: NSView (改)

カレンダークラスの UAItemViewクラスを修正し、独自のプロパティと処理を追加する。
var upper: Int
最高血圧
var lower: Int
最低血圧
var confirm: Bool
確定フラグ
var clickOpen: (( )->Void)?
日付をダブルクリックしたとき呼ばれるクロージャ。UAHealthViewクラスの clickOpenメソッドを実行し、血圧入力シートを開く。
override func draw(_ dirtyRect: NSRect)
確定フラグが真のとき、血圧入力済みの印として日付けを丸で囲む。
override func mouseDown(with event: NSEvent)
ダブルクリックしたとき clickOpenクロージャを呼ぶ。

class WinDataEntryControl: NSWindowController

血圧入力シートの制御
init( )
日付け見出し、最高血圧/最低血圧入力フィールド、確定チェックボックス、数値ボタン、登録ボタン、キャンセルボタンを作成して配置する。
func getData(date: UACalendarDate)
指定された日付の血圧データをデータベースから検索し、データがあればテキストフィールド、確定チェックボックスに表示する。
func formClose( )
更新ボタンをクリックされたとき実行する。テキストフィールド、確定チェックボックスに入力された血圧データをデータベースに更新する。その後シートを閉じる。
func formCancel( )
キャンセルボタンをクリックされたときシートを閉じる。
func updateNumber(num: Int)
数値ボタン、クリアボタンを押されたときに起動する。数値ボタンの時は数値を3桁の値に編集する。クリアボタンのときは入力中の値をクリアする。数値3桁を超えたときは次のコントロールに移る。
func changeView(_ fromView: BPValueView)
ファーストレスポンダを移動する。(最高血圧フィールド → 最高血圧フィールド → 確定チェックボックス)
func changeCheck(_ event:NSEvent)
キーコードが tabキーのときファーストレスポンダを移動する。(確定チェックボックス → 最高血圧フィールド)
キーコードが returnキーのときチェックボックスの値を反転する。

class BPButton: NSButton

数値(0〜9)ボタン、クリア(C)ボタン
var updateNumber: ((BPButton)->Void)?
数値ボタン、クリアボタンを押されたときに起動するクロージャ。WinDataEntryControlクラスの updateNumberメソッドを呼ぶ。
func mouseDown(with event: NSEvent)
背景色をクリック中の色にする。updateNumberクロージャを呼ぶ。
func mouseUp(with event: NSEvent)
背景色をもとに戻す。

class BPValueView: NSView

最高血圧/最低血圧入力フィールド
var value:Int
血圧値:設定した値は属性付き文字列に変換して入力フィールドに表示される。
var changeView: ((BPValueView) -> Void)?
カーソル(firstResponder)を次のビューに移動するクロージャ:引数は自オブジェクト
override func keyDown(with event: NSEvent)
入力が tabキーのとき、changeViewクロージャを呼び、ファーストレスポンダを次のビューに移動する。
override func draw(_ dirtyRect: NSRect)
血圧値(属性付き文字列)をビューの中央に表示する。ビューがファーストレスポンダのとき、背景色を入力中の色に変える。

class BPAcceptButton: NSButton

確定チェックボックス
var changeCheck: ((NSEvent) -> Void)?
WinDataEntryControlクラスの changeCheckねソッドを呼ぶクロージャ。
override func keyDown(with event: NSEvent)
入力が tabキーのまたは returnキーのとき、changeCheckクロージャを呼ぶ。tabキーのときはファーストレスポンダを次のビューに移動し、returnキーのときはチェックボックスを反転する。

class BPLabel: NSView

ラベルを表示するサービスクラス:属性付き文字列を表示する。フォントサイズ、文字色を指定できる。(なぜわざわざ作ったのか?)

class UATextAttribute: NSObject

属性付き文字列を作成するサービスクラス: 属性付き文字列 を参照されたい。

class WinResultControl: NSWindowController

血圧一覧表を表示する。
init( )
表示用のビューオブジェクトを作成して配置する。
func arrangeData(recordList: [RERecord], header: String)
血圧データを編集して表示する。1ヶ月分の血圧データを RERecord型オブジェクトとして作成し recordList引数に指定する。header引数には、一覧表の見出し(年月) を指定する。

class REHeaderView: NSView

表の見出し(年月)と列見出しを表示する。

class REMainView: NSView

明細行を貼り付ける基盤のビュー:適正最高血圧/適正最低血圧の補助線を引く。

class REElementView: NSView

明細行の各要素ビュー(日付、曜日、最低血圧、最高血圧、最低血圧の棒グラフ、最高血圧の棒グラフ)を作成して表示する。
var text: String
表示文字列
var backgroundColor: NSColor
背景色
var attribute: [NSAttributedString.Key:Any]
属性付き文字列の属性
var align: AlignType
文字列の横揃え:[ left, center, right ]

Webサーバとのインタフェース仕様

1. 期間を指定して血圧レコードを取得する

2. 指定した日付の血圧レコードを取得する

3. 血圧レコードを登録する

プロジェクトのダウンロード