Shreyas Sane
Explore

Coding

Estimate my Mortgage

Most mortgage calculators answer one payment. This iOS app holds several estimates side by side, because the real question is which combination you want.

Role
Sole author: design, SwiftUI implementation, App Store submission
Years
Built with
Swift, SwiftUI, Core Data, MapKit, Xcode, GitHub Actions

The comparison is the task

Every mortgage calculator computes the same amortisation. What almost none of them do is let you keep more than one answer.

While you are actually looking at houses, a single payment figure is not decision-useful. The decision is a comparison between shapes: a lower price with less down, a higher price with a better rate, a property whose taxes are noticeably worse than the one next to it. That comparison has to persist, because it forms over weeks of looking.

Property
$500,000
Down payment20%
$100,000
Borrowed
$400,000
Rate30 years
5.5%
Loan, monthly
$2,271.16
Tax, insurance, upkeep, HOA$13,500 a year
$1,125.00
Monthly
$3,396.16
Interest over the term
$417,616

Constants.swiftShreyasdbz/estimate-my-mortgage · EstimateMyMortgage/Models/

The app's seeded estimate, worked through its own formula. A third of the monthly figure never touches the loan, and the interest costs more than the amount borrowed.

So the unit in this app is a saved estimate. You name it, you keep it, you come back and change one number, and the others are still there to compare it against.

My first iOS app, and it never leaves the phone

This was my first iOS application, and its scope was chosen so that nothing about it needed a server. Estimates live in Core Data on the device. There is no account, no sync, and no analytics, and the App Store privacy declaration says the app collects no data because it collects no data.

The one external framework is MapKit, used to pin a prospective property to a place, since a typed address is hard to compare against another typed address. Everything else is local Swift: the payment maths, the treatment of taxes, insurance, and association fees, and the input validation that refuses a down payment larger than the property.

/**
 Validates that the passed downpayment is valid
 Is valid if:  lower than propertyValue AND greater than or equal to 0
 */
func validateDownpaymentValue(downpaymentValue: Double, propertyValue: Double) -> Bool {
    guard downpaymentValue < propertyValue else { return false }
    guard downpaymentValue >= 0 else { return false }
    return true
}

/**
 Interest rate must be within bounds
 Interest rate cannot be zero
 */
func validateInterestRateValue(value: Double) -> Bool {
    guard value >= RANGE_START_INTEREST_RATE && value <= RANGE_END_INTEREST_RATE else { return false }
    return true
}

CalculationUtils.swiftShreyasdbz/estimate-my-mortgage · EstimateMyMortgage/Utils/

Four guards, each written down as a sentence before it was written as code.

A single SwiftUI codebase covers iPhone, iPad, Mac on Apple Silicon, and Vision Pro.

What the first update was for

The follow-up release a day later fixed two things, and both came from using the app against a real listing that test data had never produced: address selection on the map behaved wrongly, and the home screen became hard to read once the amounts had enough digits.

The layout was fine at every figure I had typed while building it, and wrong at the figures people actually enter.