sakatore / mybalanceinquiry Goto Github PK
View Code? Open in Web Editor NEWA demo application to manage the expenditure.
A demo application to manage the expenditure.
今まで指摘してきたところを意識して、主に文法のリファクタリングをしよう。
ここのidentifier変える必要ないと思うけど
bankStatementTableView.register(UINib(nibName: "BankStatementCell", bundle: nil), forCellReuseIdentifier: "StatementCell")
//データを返すメソッド
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 1 {
switch component {
case 0:
if row == 0 {
return String("年")
} else {
let year: String = "20" + "\(17 - row)"
return year
}
こんな感じであればネストが深くなくなる。あとstringも"年"これでいい。意味わからないことしてる
//データを返すメソッド
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch (pickerView.tag, component, row) {
case (1, 0, 0): return "年"
case (1, 1, 0): return "月"
...
stract BankingData {
let type = BankType
static func type(withTitle title: String) -> BankType {
if title == "入金" {
return .payment
} else if title == "出金" {
return .withdrawal
}
ここはstaticな関数をBankingDataに定義すればここで分岐はいらなくなる
あとは
・Banking -> BankType
・class -> stract
の方がいい気がする
git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree checkout master
error: The following untracked working tree files would be overwritten by checkout:
MyBalanceInquiry/model/BankModel.swift
Please move or remove them before you can switch branches.
Aborting
Completed with errors, see above
ブランチ移動できない
let result1 = calendar.compare(data.date, to: fromDate, toGranularity: .day)
// data.date > fromDateであれば
if result1 == .orderedDescending {
let result2 = calendar.compare(data.date, to: toDate, toGranularity: .day)
// data.date < toDateであれば
if result2 == .orderedAscending {
if case .payment = data.banking {
totalBalance += data.amount
} else {
totalBalance -= data.amount
}
}
}
もっと綺麗に書けそう
Dateの比較わかりづらいから新しくオペレータ定義してみよう
swift_nsdate_compare
ここはまとめていい気がする
AppDelegateクラスはApplicationディレクトリ配下にしようか
ViewController.swift
での
// 取引を追加
myBank1.addBanking(date: dateFormatter.date(from: "2016/08/04"), banking: .withdrawal, amount: 24000)
myBank1.addBanking(date: dateFormatter.date(from: "2016/08/10"), banking: .payment, amount: 30000)
myBank1.addBanking(date: dateFormatter.date(from: "2016/08/20"), banking: .withdrawal, amount: 15000)
は1個1個書かないで、別のファイルから読み込むようにします。
機能的には影響しないですけど、テストしやすいようにするためです。
else if pickerView.tag == 2 {
let banking: [String] = ["未入力", "入金", "出金"]
ここはクラス内定数に変更して
if pickBanking == "入金" {
banking = .payment
} else if pickBanking == "出金" {
banking = .withdrawal
}
こういうところはクラス内定数から参照するようにしよう。
例えば、現状だとこの文言とかが変更になった場合何箇所も訂正する必要がある。
仕様変更に対応しやすい設計にしよう
if banking == .payment {
balance += amount
} else {
balance -= amount
}
まあこれでも悪くないんだけど
enumでパターンマッチする場合は
if case .payment = banking {
//
こういう書き方もできるし、この方がcase分のパターンマッチっぽい
マジックナンバーって言われるんだけど、ここら辺じゃぱっと見数字が何を意味しているのかわからない。
//コンポーネントに含まれるデータの個数を返すメソッド
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 1 {
switch component {
case 0:
// 2012~2016 + 「年」
return 6
case 1:
// 1~12 + 「月」
return 13
case 2:
// 1~31 + 「日」
return 32
default:
return 0
}
} else {
return 3
}
}
ここは定数として扱ってももいいんじゃないかな。stract
使うと定数をまとめることができるから今回はstract
がいいかな
例
stract DataCount {
static let year = 6
static let month = 13
...
...
case 0:
// 2012~2016 + 「年」
return DataCount.year
名前は誰が見てもわかるように考えて
~Class
っていう名前はやめよう。
基本的にMVC構成になっているのでクラス名で役割がわかるようにしよう。
例えばViewsのファイルは~View
っていうクラス、modelであれば~Model
っていう名前だとわかりやすいかな
fileprivate func getTotalBalance(fromDate: Date, toDate: Date) -> Int {
...
// fromData < toDateでなかった場合は強制終了
if calendar.compare(fromDate, to: toDate, toGranularity: .day) != .orderedAscending {
print("期間設定に誤りがあります。")
exit(0)
}
...
}
とか、
fileprivate func printBankStatement(fromDate: Date, toDate: Date) {
...
// fromData < toDateでなかった場合は強制終了
if calendar.compare(fromDate, to: toDate, toGranularity: .day) != .orderedAscending {
print("期間設定に誤りがあります。")
return;
}
...
}
のメソッドを抜ける場合の書き方って何がいいですか?
こっちもissue&Pull requestのラベルの設定を参考にしてラベルを作成しよう
MyBankViewController
では明細一覧がTableViewで表示され、セルの選択
→アラート
でBankingData
のオプション(isIncome
)を変更できる。
isIncome
がtrueであれば、セル設定時にbackgroundに色がつく。
アラートでオプションの変更後すぐに色が変わるようにしたいです。
いくつかswiftファイルを作成した時、MyBalanceInquiryディレクトリの外に作ってしまったので中に入れたい。
ただ移動させるだけだと、xcodeで開けなくなるのでどうすればいいですか?
まず、これでclass typeからクラス名をstringで取得可能
extension String {
static func className(_ aClass: AnyClass) -> String {
guard let className = NSStringFromClass(aClass).components(separatedBy: ".").last else { return "" }
return className
}
次にUITableViewExtension.swift
でも作れば
extension UITableView {
func registerCells<T: UITableViewCell>(_ types: [T.Type]) {
types.forEach { registerCell($0) }
}
func registerCells<T: UITableViewCell>(_ types: [[T.Type]]) {
types.flatMap{$0.prefix(upTo: 1)}.forEach { registerCell($0) }
}
func dequeueCell<T: UITableViewCell>(_ type: T.Type, indexPath: IndexPath) -> T {
return dequeueReusableCell(withIdentifier: String.className(type), for: indexPath) as! T
}
bankStatementTableView.register(UINib(nibName: "BankStatementCell", bundle: nil), forCellReuseIdentifier: "BankStatementCell")
->
tableView.registerCell(BankStatementCell.self)
tableView.dequeueReusableCell(withIdentifier: "BankStatementCell", for: indexPath)
->
tableView.dequeueCell(BankStatementCell.self, indexPath: indexPath)
で直接stringを渡すことなくcellの管理可能
// 過去全ての取引を計算する
fileprivate func getTotalBalance() -> Int {
var totalBalance = firstBalance
bankStatement.forEach { data in
if case .payment = data.banking {
totalBalance += data.amount
} else {
totalBalance -= data.amount
}
}
return totalBalance
}
単に状態によって残高返すから変数で行けそう
stringでみずほ銀行とか入れるのってちょっと行けてない感じがある。
多分普通のアプリに置き換えて考えたら、扱える銀行って数社くらいだと思うんだよね。そう考えるとアプリ内で銀行定義しちゃっていいと思うから、ここはenumで指定できるとsafetyなきがする。
let myBank1 = Bank(name: "みずほ銀行", firstBalance: 100000)
let myBank2 = Bank(name: "三菱東京UFJ銀行", firstBalance: 200000)
let myBank3 = Bank(name: "多摩信用金庫", firstBalance: 1200000)
enum BankType {
case mizuho, mitsubishi, ...
}
let myBank1 = Bank(type: .mizuho, firstBalance: 100000)
let myBank2 = Bank(name: .mitsubishi, firstBalance: 200000)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.