help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • Blog
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
swift-ios-calculator
RSK World
swift-ios-calculator
Swift iOS Calculator v1.0 - AI Math Solver + 3D Graphing + Apple Watch Integration + iOS Widgets + Siri Shortcuts + Currency Converter + Scientific Calculator + Matrix Operations + Platform Integration + Modern iOS Development
swift-ios-calculator
  • Assets.xcassets
  • Base.lproj
  • swift-ios-calculator.xcodeproj
  • AIMathSolverViewController.swift26.6 KB
  • AppDelegate.swift1.7 KB
  • CalculatorHistoryViewController.swift6.5 KB
  • CalculatorLogic.swift4.4 KB
  • CalculatorSettingsViewController.swift5.6 KB
  • CalculatorTheme.swift8.3 KB
  • CalculatorUtils.swift6.9 KB
  • CalculatorViewController.swift3.4 KB
  • CalculatorWidget.swift14.3 KB
  • CalculatorWidgetInfo.plist846 B
  • ChemistryCalculatorViewController.swift26.9 KB
  • CurrencyConverterViewController.swift13.3 KB
  • CustomFormulaBuilderViewController.swift22.1 KB
  • EngineeringCalculatorViewController.swift25.7 KB
  • EquationSolverViewController.swift22.8 KB
  • FinancialCalculatorViewController.swift27.5 KB
  • GeometryCalculatorViewController.swift29.7 KB
  • Graphing3DViewController.swift20.8 KB
  • GraphingCalculatorViewController.swift14.7 KB
  • Info.plist3.2 KB
  • LICENSE1.1 KB
  • MainTabBarController.swift22.3 KB
  • MatrixCalculatorViewController.swift26.6 KB
  • PRIVACY_POLICY.md1.6 KB
  • PhysicsCalculatorService.swift8.2 KB
  • ProgrammerCalculatorViewController.swift11 KB
  • README.md8.7 KB
  • RELEASE_NOTES.md6.5 KB
  • SceneDelegate.swift2.8 KB
  • ScientificCalculatorViewController.swift6.2 KB
  • SiriShortcutsManager.swift23.5 KB
  • Swift iOS Calculator.entitlements1.1 KB
  • UnitConverterViewController.swift14 KB
  • WatchCalculatorViewController.swift15.3 KB
  • index.html47.5 KB
GraphingCalculatorViewController.swiftFinancialCalculatorViewController.swift
GraphingCalculatorViewController.swift
Raw Download
Find: Go to:
//
//  GraphingCalculatorViewController.swift
//  Swift iOS Calculator
//
//  Created by RSK World on 23/01/2026.
//  Copyright © 2026 RSK World. All rights reserved.
//
//  Developer: Molla Samser (Founder, RSK World)
//  Designer & Tester: Rima Khatun
//  Contact: info@rskworld.com, +91 93305 39277
//  Website: https://rskworld.in
//  Address: Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India - 713147
//

import UIKit
import CoreGraphics

class GraphingCalculatorViewController: UIViewController {
    
    // MARK: - Outlets
    @IBOutlet weak var graphView: GraphView!
    @IBOutlet weak var functionTextField: UITextField!
    @IBOutlet weak var xMinTextField: UITextField!
    @IBOutlet weak var xMaxTextField: UITextField!
    @IBOutlet weak var yMinTextField: UITextField!
    @IBOutlet weak var yMaxTextField: UITextField!
    @IBOutlet weak var plotButton: UIButton!
    @IBOutlet weak var clearButton: UIButton!
    @IBOutlet weak var zoomInButton: UIButton!
    @IBOutlet weak var zoomOutButton: UIButton!
    @IBOutlet weak var resetButton: UIButton!
    @IBOutlet weak var functionSegmentedControl: UISegmentedControl!
    
    // MARK: - Properties
    private var functions: [String] = []
    private var colors: [UIColor] = [.systemBlue, .systemRed, .systemGreen, .systemOrange, .systemPurple, .systemPink]
    private var currentFunctionIndex = 0
    
    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupGraphView()
    }
    
    // MARK: - Setup
    private func setupUI() {
        title = "Graphing Calculator"
        view.backgroundColor = CalculatorTheme.shared.backgroundColor
        
        // Setup text fields
        setupTextField(functionTextField, placeholder: "Enter function (e.g., x^2, sin(x), cos(x))")
        setupTextField(xMinTextField, placeholder: "-10")
        setupTextField(xMaxTextField, placeholder: "10")
        setupTextField(yMinTextField, placeholder: "-10")
        setupTextField(yMaxTextField, placeholder: "10")
        
        // Set default values
        xMinTextField.text = "-10"
        xMaxTextField.text = "10"
        yMinTextField.text = "-10"
        yMaxTextField.text = "10"
        
        // Setup buttons
        setupButton(plotButton, title: "Plot", color: .systemGreen)
        setupButton(clearButton, title: "Clear", color: .systemRed)
        setupButton(zoomInButton, title: "Zoom In", color: .systemBlue)
        setupButton(zoomOutButton, title: "Zoom Out", color: .systemBlue)
        setupButton(resetButton, title: "Reset", color: .systemGray)
        
        // Setup segmented control
        functionSegmentedControl.backgroundColor = CalculatorTheme.shared.buttonBackgroundColor
        functionSegmentedControl.selectedSegmentTintColor = CalculatorTheme.shared.accentColor
        functionSegmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: CalculatorTheme.shared.textColor], for: .normal)
        functionSegmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .selected)
    }
    
    private func setupTextField(_ textField: UITextField, placeholder: String) {
        textField.backgroundColor = CalculatorTheme.shared.displayBackgroundColor
        textField.textColor = CalculatorTheme.shared.textColor
        textField.placeholder = placeholder
        textField.layer.cornerRadius = 8
        textField.layer.borderWidth = 1
        textField.layer.borderColor = CalculatorTheme.shared.buttonBackgroundColor.cgColor
        textField.textAlignment = .center
    }
    
    private func setupButton(_ button: UIButton, title: String, color: UIColor) {
        button.setTitle(title, for: .normal)
        button.backgroundColor = color
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 8
    }
    
    private func setupGraphView() {
        graphView.backgroundColor = CalculatorTheme.shared.displayBackgroundColor
        graphView.layer.cornerRadius = 12
        graphView.layer.borderWidth = 2
        graphView.layer.borderColor = CalculatorTheme.shared.buttonBackgroundColor.cgColor
    }
    
    // MARK: - Actions
    @IBAction func plotButtonPressed(_ sender: UIButton) {
        guard let function = functionTextField.text, !function.isEmpty else {
            showAlert(message: "Please enter a function to plot")
            return
        }
        
        guard let xMin = Double(xMinTextField.text ?? ""),
              let xMax = Double(xMaxTextField.text ?? ""),
              let yMin = Double(yMinTextField.text ?? ""),
              let yMax = Double(yMaxTextField.text ?? "") else {
            showAlert(message: "Please enter valid numeric values for the range")
            return
        }
        
        if xMin >= xMax || yMin >= yMax {
            showAlert(message: "Minimum values must be less than maximum values")
            return
        }
        
        // Add function to list
        if currentFunctionIndex >= functions.count {
            functions.append(function)
        } else {
            functions[currentFunctionIndex] = function
        }
        
        // Update segmented control
        if currentFunctionIndex >= functionSegmentedControl.numberOfSegments {
            functionSegmentedControl.insertSegment(withTitle: "f\(currentFunctionIndex + 1)(x)", at: currentFunctionIndex, animated: true)
        }
        functionSegmentedControl.selectedSegmentIndex = currentFunctionIndex
        
        // Plot the function
        plotFunction(function, xMin: xMin, xMax: xMax, yMin: yMin, yMax: yMax)
        
        // Move to next function
        currentFunctionIndex = (currentFunctionIndex + 1) % 6
        functionTextField.text = ""
    }
    
    @IBAction func clearButtonPressed(_ sender: UIButton) {
        graphView.clearGraph()
        functions.removeAll()
        currentFunctionIndex = 0
        
        // Clear segmented control
        while functionSegmentedControl.numberOfSegments > 0 {
            functionSegmentedControl.removeSegment(at: 0, animated: true)
        }
    }
    
    @IBAction func zoomInButtonPressed(_ sender: UIButton) {
        guard let xMin = Double(xMinTextField.text ?? ""),
              let xMax = Double(xMaxTextField.text ?? ""),
              let yMin = Double(yMinTextField.text ?? ""),
              let yMax = Double(yMaxTextField.text ?? "") else { return }
        
        let xCenter = (xMin + xMax) / 2
        let yCenter = (yMin + yMax) / 2
        let xRange = (xMax - xMin) * 0.4
        let yRange = (yMax - yMin) * 0.4
        
        xMinTextField.text = String(xCenter - xRange)
        xMaxTextField.text = String(xCenter + xRange)
        yMinTextField.text = String(yCenter - yRange)
        yMaxTextField.text = String(yCenter + yRange)
        
        replotAllFunctions()
    }
    
    @IBAction func zoomOutButtonPressed(_ sender: UIButton) {
        guard let xMin = Double(xMinTextField.text ?? ""),
              let xMax = Double(xMaxTextField.text ?? ""),
              let yMin = Double(yMinTextField.text ?? ""),
              let yMax = Double(yMaxTextField.text ?? "") else { return }
        
        let xCenter = (xMin + xMax) / 2
        let yCenter = (yMin + yMax) / 2
        let xRange = (xMax - xMin) * 0.6
        let yRange = (yMax - yMin) * 0.6
        
        xMinTextField.text = String(xCenter - xRange)
        xMaxTextField.text = String(xCenter + xRange)
        yMinTextField.text = String(yCenter - yRange)
        yMaxTextField.text = String(yCenter + yRange)
        
        replotAllFunctions()
    }
    
    @IBAction func resetButtonPressed(_ sender: UIButton) {
        xMinTextField.text = "-10"
        xMaxTextField.text = "10"
        yMinTextField.text = "-10"
        yMaxTextField.text = "10"
        replotAllFunctions()
    }
    
    @IBAction func functionChanged(_ sender: UISegmentedControl) {
        currentFunctionIndex = sender.selectedSegmentIndex
        if currentFunctionIndex < functions.count {
            functionTextField.text = functions[currentFunctionIndex]
        }
    }
    
    // MARK: - Methods
    private func plotFunction(_ function: String, xMin: Double, xMax: Double, yMin: Double, yMax: Double) {
        let points = calculatePoints(for: function, xMin: xMin, xMax: xMax, yMin: yMin, yMax: yMax)
        let color = colors[currentFunctionIndex % colors.count]
        graphView.plotFunction(points: points, color: color, xMin: xMin, xMax: xMax, yMin: yMin, yMax: yMax)
    }
    
    private func calculatePoints(for function: String, xMin: Double, xMax: Double, yMin: Double, yMax: Double) -> [CGPoint] {
        var points: [CGPoint] = []
        let steps = 500
        let stepSize = (xMax - xMin) / Double(steps)
        
        for i in 0...steps {
            let x = xMin + Double(i) * stepSize
            let y = evaluateFunction(function, at: x)
            
            if !y.isNaN && !y.isInfinite && y >= yMin && y <= yMax {
                let normalizedX = (x - xMin) / (xMax - xMin)
                let normalizedY = 1.0 - (y - yMin) / (yMax - yMin)
                points.append(CGPoint(x: normalizedX, y: normalizedY))
            }
        }
        
        return points
    }
    
    private func evaluateFunction(_ function: String, at x: Double) -> Double {
        let expression = function.lowercased()
            .replacingOccurrences(of: "x", with: "(\(x))")
            .replacingOccurrences(of: "^", with: "**")
            .replacingOccurrences(of: "sin", with: "Foundation.sin")
            .replacingOccurrences(of: "cos", with: "Foundation.cos")
            .replacingOccurrences(of: "tan", with: "Foundation.tan")
            .replacingOccurrences(of: "log", with: "Foundation.log")
            .replacingOccurrences(of: "ln", with: "Foundation.log")
            .replacingOccurrences(of: "sqrt", with: "Foundation.sqrt")
            .replacingOccurrences(of: "abs", with: "Foundation.abs")
            .replacingOccurrences(of: "exp", with: "Foundation.exp")
            .replacingOccurrences(of: "pi", with: "Double.pi")
            .replacingOccurrences(of: "e", with: "Foundation.exp(1)")
        
        let expressionParser = ExpressionParser()
        return expressionParser.evaluate(expression)
    }
    
    private func replotAllFunctions() {
        guard let xMin = Double(xMinTextField.text ?? ""),
              let xMax = Double(xMaxTextField.text ?? ""),
              let yMin = Double(yMinTextField.text ?? ""),
              let yMax = Double(yMaxTextField.text ?? "") else { return }
        
        graphView.clearGraph()
        
        for (index, function) in functions.enumerated() {
            let points = calculatePoints(for: function, xMin: xMin, xMax: xMax, yMin: yMin, yMax: yMax)
            let color = colors[index % colors.count]
            graphView.plotFunction(points: points, color: color, xMin: xMin, xMax: xMax, yMin: yMin, yMax: yMax)
        }
    }
    
    private func showAlert(message: String) {
        let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

// MARK: - GraphView
class GraphView: UIView {
    
    private var functionPaths: [UIBezierPath] = []
    private var functionColors: [UIColor] = []
    private var xMin: Double = -10
    private var xMax: Double = 10
    private var yMin: Double = -10
    private var yMax: Double = 10
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        guard let context = UIGraphicsGetCurrentContext() else { return }
        
        // Draw grid
        drawGrid(in: context, rect: rect)
        
        // Draw axes
        drawAxes(in: context, rect: rect)
        
        // Draw functions
        for (index, path) in functionPaths.enumerated() {
            functionColors[index].setStroke()
            path.lineWidth = 2.0
            path.stroke()
        }
    }
    
    private func drawGrid(in context: CGContext, rect: CGRect) {
        context.setStrokeColor(UIColor.systemGray4.cgColor)
        context.setLineWidth(0.5)
        
        // Vertical lines
        for i in 0...10 {
            let x = rect.width * CGFloat(i) / 10.0
            context.move(to: CGPoint(x: x, y: 0))
            context.addLine(to: CGPoint(x: x, y: rect.height))
        }
        
        // Horizontal lines
        for i in 0...10 {
            let y = rect.height * CGFloat(i) / 10.0
            context.move(to: CGPoint(x: 0, y: y))
            context.addLine(to: CGPoint(x: rect.width, y: y))
        }
        
        context.strokePath()
    }
    
    private func drawAxes(in context: CGContext, rect: CGRect) {
        context.setStrokeColor(UIColor.label.cgColor)
        context.setLineWidth(2.0)
        
        // X-axis
        let yZero = rect.height * CGFloat((yMax) / (yMax - yMin))
        context.move(to: CGPoint(x: 0, y: yZero))
        context.addLine(to: CGPoint(x: rect.width, y: yZero))
        
        // Y-axis
        let xZero = rect.width * CGFloat((-xMin) / (xMax - xMin))
        context.move(to: CGPoint(x: xZero, y: 0))
        context.addLine(to: CGPoint(x: xZero, y: rect.height))
        
        context.strokePath()
    }
    
    func plotFunction(points: [CGPoint], color: UIColor, xMin: Double, xMax: Double, yMin: Double, yMax: Double) {
        self.xMin = xMin
        self.xMax = xMax
        self.yMin = yMin
        self.yMax = yMax
        
        let path = UIBezierPath()
        
        for (index, point) in points.enumerated() {
            let x = point.x * bounds.width
            let y = point.y * bounds.height
            
            if index == 0 {
                path.move(to: CGPoint(x: x, y: y))
            } else {
                path.addLine(to: CGPoint(x: x, y: y))
            }
        }
        
        functionPaths.append(path)
        functionColors.append(color)
        setNeedsDisplay()
    }
    
    func clearGraph() {
        functionPaths.removeAll()
        functionColors.removeAll()
        setNeedsDisplay()
    }
}

// MARK: - Expression Parser
class ExpressionParser {
    
    func evaluate(_ expression: String) -> Double {
        // Simple expression evaluator
        // In a real app, you'd use a more sophisticated parser
        let nsExpression = NSExpression(format: expression)
        return nsExpression.expressionValue(with: nil, context: nil) as? Double ?? 0.0
    }
}
382 lines•14.7 KB
swift
FinancialCalculatorViewController.swift
Raw Download
Find: Go to:
//
//  FinancialCalculatorViewController.swift
//  Swift iOS Calculator
//
//  Created by RSK World on 23/01/2026.
//  Copyright © 2026 RSK World. All rights reserved.
//
//  Developer: Molla Samser (Founder, RSK World)
//  Designer & Tester: Rima Khatun
//  Contact: info@rskworld.com, +91 93305 39277
//  Website: https://rskworld.in
//  Address: Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India - 713147
//

import UIKit

class FinancialCalculatorViewController: UIViewController {
    
    // MARK: - Outlets
    @IBOutlet weak var calculatorSegmentedControl: UISegmentedControl!
    @IBOutlet weak var inputContainerView: UIView!
    @IBOutlet weak var resultTextView: UITextView!
    @IBOutlet weak var calculateButton: UIButton!
    @IBOutlet weak var clearButton: UIButton!
    
    // Investment Calculator Outlets
    @IBOutlet weak var principalTextField: UITextField!
    @IBOutlet weak var interestRateTextField: UITextField!
    @IBOutlet weak var timePeriodTextField: UITextField!
    @IBOutlet weak var compoundFrequencySegmentedControl: UISegmentedControl!
    
    // Loan Calculator Outlets
    @IBOutlet weak var loanAmountTextField: UITextField!
    @IBOutlet weak var loanInterestRateTextField: UITextField!
    @IBOutlet weak var loanTermTextField: UITextField!
    @IBOutlet weak var downPaymentTextField: UITextField!
    
    // Retirement Calculator Outlets
    @IBOutlet weak var currentAgeTextField: UITextField!
    @IBOutlet weak var retirementAgeTextField: UITextField!
    @IBOutlet weak var currentSavingsTextField: UITextField!
    @IBOutlet weak var monthlyContributionTextField: UITextField!
    @IBOutlet weak var retirementGoalTextField: UITextField!
    
    // MARK: - Properties
    private var currentCalculator: FinancialCalculatorType = .investment
    private let financialCalculator = FinancialCalculatorService()
    
    enum FinancialCalculatorType: String, CaseIterable {
        case investment = "Investment"
        case loan = "Loan"
        case retirement = "Retirement"
        case savings = "Savings"
        case mortgage = "Mortgage"
        case depreciation = "Depreciation"
        
        var icon: String {
            switch self {
            case .investment: return "chart.line.uptrend.xyaxis"
            case .loan: return "dollarsign.circle"
            case .retirement: return "pencil.and.ellipsis.rectangle"
            case .savings: return "banknote"
            case .mortgage: return "house"
            case .depreciation: return "minus.circle"
            }
        }
    }
    
    // MARK: - Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupSegmentedControl()
        setupInputViews()
        showInvestmentCalculator()
    }
    
    // MARK: - Setup
    private func setupUI() {
        title = "Financial Calculator"
        view.backgroundColor = CalculatorTheme.shared.backgroundColor
        
        // Setup result text view
        resultTextView.backgroundColor = CalculatorTheme.shared.displayBackgroundColor
        resultTextView.textColor = CalculatorTheme.shared.textColor
        resultTextView.layer.cornerRadius = 12
        resultTextView.layer.borderWidth = 2
        resultTextView.layer.borderColor = CalculatorTheme.shared.accentColor.cgColor
        resultTextView.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        resultTextView.isEditable = false
        
        // Setup buttons
        setupButton(calculateButton, title: "Calculate", color: .systemGreen)
        setupButton(clearButton, title: "Clear", color: .systemRed)
    }
    
    private func setupButton(_ button: UIButton, title: String, color: UIColor) {
        button.setTitle(title, for: .normal)
        button.backgroundColor = color
        button.setTitleColor(.white, for: .normal)
        button.layer.cornerRadius = 8
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
    }
    
    private func setupSegmentedControl() {
        calculatorSegmentedControl.removeAllSegments()
        for (index, type) in FinancialCalculatorType.allCases.enumerated() {
            calculatorSegmentedControl.insertSegment(withTitle: type.rawValue, at: index, animated: false)
        }
        calculatorSegmentedControl.selectedSegmentIndex = 0
        calculatorSegmentedControl.backgroundColor = CalculatorTheme.shared.buttonBackgroundColor
        calculatorSegmentedControl.selectedSegmentTintColor = CalculatorTheme.shared.accentColor
        calculatorSegmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: CalculatorTheme.shared.textColor], for: .normal)
        calculatorSegmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .selected)
    }
    
    private func setupInputViews() {
        // Setup all text fields with consistent styling
        let textFields = [
            principalTextField, interestRateTextField, timePeriodTextField,
            loanAmountTextField, loanInterestRateTextField, loanTermTextField, downPaymentTextField,
            currentAgeTextField, retirementAgeTextField, currentSavingsTextField,
            monthlyContributionTextField, retirementGoalTextField
        ].compactMap { $0 }
        
        for textField in textFields {
            textField.backgroundColor = CalculatorTheme.shared.displayBackgroundColor
            textField.textColor = CalculatorTheme.shared.textColor
            textField.layer.cornerRadius = 8
            textField.layer.borderWidth = 1
            textField.layer.borderColor = CalculatorTheme.shared.buttonBackgroundColor.cgColor
            textField.textAlignment = .center
            textField.font = UIFont.systemFont(ofSize: 16)
            textField.keyboardType = .decimalPad
        }
        
        // Setup segmented controls
        setupSegmentedControl(compoundFrequencySegmentedControl, titles: ["Annually", "Semi-Annually", "Quarterly", "Monthly"])
    }
    
    private func setupSegmentedControl(_ segmentedControl: UISegmentedControl, titles: [String]) {
        segmentedControl.removeAllSegments()
        for (index, title) in titles.enumerated() {
            segmentedControl.insertSegment(withTitle: title, at: index, animated: false)
        }
        segmentedControl.selectedSegmentIndex = 0
        segmentedControl.backgroundColor = CalculatorTheme.shared.buttonBackgroundColor
        segmentedControl.selectedSegmentTintColor = CalculatorTheme.shared.accentColor
        segmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: CalculatorTheme.shared.textColor], for: .normal)
        segmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .selected)
    }
    
    // MARK: - Actions
    @IBAction func calculatorTypeChanged(_ sender: UISegmentedControl) {
        currentCalculator = FinancialCalculatorType.allCases[sender.selectedSegmentIndex]
        switchToCalculator(currentCalculator)
    }
    
    @IBAction func calculateButtonPressed(_ sender: UIButton) {
        performCalculation()
    }
    
    @IBAction func clearButtonPressed(_ sender: UIButton) {
        clearAllInputs()
    }
    
    @IBAction func compoundFrequencyChanged(_ sender: UISegmentedControl) {
        // Handle compound frequency change
    }
    
    // MARK: - Methods
    private func switchToCalculator(_ type: FinancialCalculatorType) {
        // Hide all input views first
        hideAllInputViews()
        
        switch type {
        case .investment:
            showInvestmentCalculator()
        case .loan:
            showLoanCalculator()
        case .retirement:
            showRetirementCalculator()
        case .savings:
            showSavingsCalculator()
        case .mortgage:
            showMortgageCalculator()
        case .depreciation:
            showDepreciationCalculator()
        }
        
        clearResult()
    }
    
    private func hideAllInputViews() {
        inputContainerView.subviews.forEach { $0.isHidden = true }
    }
    
    private func showInvestmentCalculator() {
        principalTextField.isHidden = false
        interestRateTextField.isHidden = false
        timePeriodTextField.isHidden = false
        compoundFrequencySegmentedControl.isHidden = false
        
        principalTextField.placeholder = "Principal Amount ($)"
        interestRateTextField.placeholder = "Annual Interest Rate (%)"
        timePeriodTextField.placeholder = "Time Period (Years)"
    }
    
    private func showLoanCalculator() {
        loanAmountTextField.isHidden = false
        loanInterestRateTextField.isHidden = false
        loanTermTextField.isHidden = false
        downPaymentTextField.isHidden = false
        
        loanAmountTextField.placeholder = "Loan Amount ($)"
        loanInterestRateTextField.placeholder = "Interest Rate (%)"
        loanTermTextField.placeholder = "Loan Term (Years)"
        downPaymentTextField.placeholder = "Down Payment ($)"
    }
    
    private func showRetirementCalculator() {
        currentAgeTextField.isHidden = false
        retirementAgeTextField.isHidden = false
        currentSavingsTextField.isHidden = false
        monthlyContributionTextField.isHidden = false
        retirementGoalTextField.isHidden = false
        
        currentAgeTextField.placeholder = "Current Age"
        retirementAgeTextField.placeholder = "Retirement Age"
        currentSavingsTextField.placeholder = "Current Savings ($)"
        monthlyContributionTextField.placeholder = "Monthly Contribution ($)"
        retirementGoalTextField.placeholder = "Retirement Goal ($)"
    }
    
    private func showSavingsCalculator() {
        principalTextField.isHidden = false
        interestRateTextField.isHidden = false
        timePeriodTextField.isHidden = false
        monthlyContributionTextField.isHidden = false
        
        principalTextField.placeholder = "Initial Amount ($)"
        interestRateTextField.placeholder = "Interest Rate (%)"
        timePeriodTextField.placeholder = "Time Period (Years)"
        monthlyContributionTextField.placeholder = "Monthly Contribution ($)"
    }
    
    private func showMortgageCalculator() {
        loanAmountTextField.isHidden = false
        loanInterestRateTextField.isHidden = false
        loanTermTextField.isHidden = false
        downPaymentTextField.isHidden = false
        
        loanAmountTextField.placeholder = "Home Price ($)"
        loanInterestRateTextField.placeholder = "Interest Rate (%)"
        loanTermTextField.placeholder = "Loan Term (Years)"
        downPaymentTextField.placeholder = "Down Payment ($)"
    }
    
    private func showDepreciationCalculator() {
        principalTextField.isHidden = false
        interestRateTextField.isHidden = false
        timePeriodTextField.isHidden = false
        
        principalTextField.placeholder = "Asset Value ($)"
        interestRateTextField.placeholder = "Depreciation Rate (%)"
        timePeriodTextField.placeholder = "Useful Life (Years)"
    }
    
    private func performCalculation() {
        view.endEditing(true)
        
        switch currentCalculator {
        case .investment:
            calculateInvestment()
        case .loan:
            calculateLoan()
        case .retirement:
            calculateRetirement()
        case .savings:
            calculateSavings()
        case .mortgage:
            calculateMortgage()
        case .depreciation:
            calculateDepreciation()
        }
    }
    
    private func calculateInvestment() {
        guard let principal = Double(principalTextField.text ?? ""),
              let rate = Double(interestRateTextField.text ?? ""),
              let time = Double(timePeriodTextField.text ?? "") else {
            showError("Please enter valid input values")
            return
        }
        
        let frequency = getCompoundFrequency()
        let result = financialCalculator.calculateInvestment(
            principal: principal,
            rate: rate,
            time: time,
            frequency: frequency
        )
        
        displayResult(result)
    }
    
    private func calculateLoan() {
        guard let amount = Double(loanAmountTextField.text ?? ""),
              let rate = Double(loanInterestRateTextField.text ?? ""),
              let term = Double(loanTermTextField.text ?? "") else {
            showError("Please enter valid loan details")
            return
        }
        
        let downPayment = Double(downPaymentTextField.text ?? "") ?? 0
        let result = financialCalculator.calculateLoan(
            amount: amount,
            rate: rate,
            term: term,
            downPayment: downPayment
        )
        
        displayResult(result)
    }
    
    private func calculateRetirement() {
        guard let currentAge = Int(currentAgeTextField.text ?? ""),
              let retirementAge = Int(retirementAgeTextField.text ?? ""),
              let currentSavings = Double(currentSavingsTextField.text ?? ""),
              let monthlyContribution = Double(monthlyContributionTextField.text ?? ""),
              let retirementGoal = Double(retirementGoalTextField.text ?? "") else {
            showError("Please enter valid retirement details")
            return
        }
        
        let result = financialCalculator.calculateRetirement(
            currentAge: currentAge,
            retirementAge: retirementAge,
            currentSavings: currentSavings,
            monthlyContribution: monthlyContribution,
            retirementGoal: retirementGoal
        )
        
        displayResult(result)
    }
    
    private func calculateSavings() {
        guard let principal = Double(principalTextField.text ?? ""),
              let rate = Double(interestRateTextField.text ?? ""),
              let time = Double(timePeriodTextField.text ?? ""),
              let monthlyContribution = Double(monthlyContributionTextField.text ?? "") else {
            showError("Please enter valid savings details")
            return
        }
        
        let result = financialCalculator.calculateSavings(
            principal: principal,
            rate: rate,
            time: time,
            monthlyContribution: monthlyContribution
        )
        
        displayResult(result)
    }
    
    private func calculateMortgage() {
        guard let homePrice = Double(loanAmountTextField.text ?? ""),
              let rate = Double(loanInterestRateTextField.text ?? ""),
              let term = Double(loanTermTextField.text ?? "") else {
            showError("Please enter valid mortgage details")
            return
        }
        
        let downPayment = Double(downPaymentTextField.text ?? "") ?? 0
        let result = financialCalculator.calculateMortgage(
            homePrice: homePrice,
            rate: rate,
            term: term,
            downPayment: downPayment
        )
        
        displayResult(result)
    }
    
    private func calculateDepreciation() {
        guard let assetValue = Double(principalTextField.text ?? ""),
              let rate = Double(interestRateTextField.text ?? ""),
              let usefulLife = Double(timePeriodTextField.text ?? "") else {
            showError("Please enter valid depreciation details")
            return
        }
        
        let result = financialCalculator.calculateDepreciation(
            assetValue: assetValue,
            rate: rate,
            usefulLife: usefulLife
        )
        
        displayResult(result)
    }
    
    private func getCompoundFrequency() -> CompoundFrequency {
        switch compoundFrequencySegmentedControl.selectedSegmentIndex {
        case 0: return .annually
        case 1: return .semiAnnually
        case 2: return .quarterly
        case 3: return .monthly
        default: return .annually
        }
    }
    
    private func displayResult(_ result: FinancialCalculationResult) {
        let resultText = formatResult(result)
        resultTextView.text = resultText
        
        // Animate result appearance
        resultTextView.alpha = 0
        UIView.animate(withDuration: 0.5) {
            self.resultTextView.alpha = 1
        }
        
        // Save to history
        saveToHistory(result: resultText)
    }
    
    private func formatResult(_ result: FinancialCalculationResult) -> String {
        var formattedResult = ""
        
        switch result {
        case .investment(let futureValue, let totalInterest):
            formattedResult = """
            📈 Investment Results
            
            Future Value: $\(String(format: "%.2f", futureValue))
            Total Interest Earned: $\(String(format: "%.2f", totalInterest))
            
            Breakdown:
            • Principal: $\(String(format: "%.2f", result.principal))
            • Interest: $\(String(format: "%.2f", totalInterest))
            • Total: $\(String(format: "%.2f", futureValue))
            """
            
        case .loan(let monthlyPayment, let totalInterest, let totalPayment):
            formattedResult = """
            💰 Loan Results
            
            Monthly Payment: $\(String(format: "%.2f", monthlyPayment))
            Total Interest: $\(String(format: "%.2f", totalInterest))
            Total Payment: $\(String(format: "%.2f", totalPayment))
            
            Loan Details:
            • Principal: $\(String(format: "%.2f", result.principal))
            • Interest: $\(String(format: "%.2f", totalInterest))
            • Total: $\(String(format: "%.2f", totalPayment))
            """
            
        case .retirement(let projectedSavings, let monthlyNeeded, let isGoalMet):
            formattedResult = """
            🏖️ Retirement Planning
            
            Projected Savings: $\(String(format: "%.2f", projectedSavings))
            Monthly Contribution Needed: $\(String(format: "%.2f", monthlyNeeded))
            Goal Status: \(isGoalMet ? "✅ On Track" : "⚠️ Adjust Contributions")
            
            Retirement Details:
            • Current Age: \(result.currentAge)
            • Retirement Age: \(result.retirementAge)
            • Years to Retirement: \(result.retirementAge - result.currentAge)
            """
            
        case .savings(let futureValue, let totalInterest):
            formattedResult = """
            💵 Savings Results
            
            Future Value: $\(String(format: "%.2f", futureValue))
            Total Interest Earned: $\(String(format: "%.2f", totalInterest))
            
            Savings Breakdown:
            • Initial: $\(String(format: "%.2f", result.principal))
            • Contributions: $\(String(format: "%.2f", result.monthlyContribution * Double(result.time * 12)))
            • Interest: $\(String(format: "%.2f", totalInterest))
            • Total: $\(String(format: "%.2f", futureValue))
            """
            
        case .mortgage(let monthlyPayment, let totalInterest, let totalPayment):
            formattedResult = """
            🏠 Mortgage Results
            
            Monthly Payment: $\(String(format: "%.2f", monthlyPayment))
            Total Interest: $\(String(format: "%.2f", totalInterest))
            Total Payment: $\(String(format: "%.2f", totalPayment))
            
            Mortgage Details:
            • Home Price: $\(String(format: "%.2f", result.principal))
            • Down Payment: $\(String(format: "%.2f", result.downPayment))
            • Loan Amount: $\(String(format: "%.2f", result.principal - result.downPayment))
            • Interest: $\(String(format: "%.2f", totalInterest))
            """
            
        case .depreciation(let annualDepreciation, let bookValue, let accumulatedDepreciation):
            formattedResult = """
            📉 Depreciation Results
            
            Annual Depreciation: $\(String(format: "%.2f", annualDepreciation))
            Current Book Value: $\(String(format: "%.2f", bookValue))
            Accumulated Depreciation: $\(String(format: "%.2f", accumulatedDepreciation))
            
            Asset Details:
            • Original Value: $\(String(format: "%.2f", result.principal))
            • Rate: \(result.rate)%
            • Useful Life: \(result.time) years
            """
        }
        
        return formattedResult
    }
    
    private func clearAllInputs() {
        let textFields = [
            principalTextField, interestRateTextField, timePeriodTextField,
            loanAmountTextField, loanInterestRateTextField, loanTermTextField, downPaymentTextField,
            currentAgeTextField, retirementAgeTextField, currentSavingsTextField,
            monthlyContributionTextField, retirementGoalTextField
        ].compactMap { $0 }
        
        for textField in textFields {
            textField.text = ""
        }
        
        clearResult()
    }
    
    private func clearResult() {
        resultTextView.text = "Results will appear here..."
    }
    
    private func saveToHistory(result: String) {
        let historyItem = CalculationHistoryItem(
            expression: "\(currentCalculator.rawValue) Calculation",
            result: result,
            category: "Financial Calculator",
            date: Date()
        )
        
        CalculationHistoryManager.shared.addHistoryItem(historyItem)
    }
    
    private func showError(_ message: String) {
        let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

// MARK: - Financial Calculator Service
class FinancialCalculatorService {
    
    func calculateInvestment(principal: Double, rate: Double, time: Double, frequency: CompoundFrequency) -> FinancialCalculationResult {
        let r = rate / 100
        let n = getCompoundingPeriodsPerYear(frequency)
        let t = time
        
        let futureValue = principal * pow(1 + r/n, n*t)
        let totalInterest = futureValue - principal
        
        return .investment(futureValue: futureValue, totalInterest: totalInterest)
    }
    
    func calculateLoan(amount: Double, rate: Double, term: Double, downPayment: Double) -> FinancialCalculationResult {
        let principal = amount - downPayment
        let monthlyRate = (rate / 100) / 12
        let numberOfPayments = term * 12
        
        let monthlyPayment = principal * monthlyRate * pow(1 + monthlyRate, numberOfPayments) / (pow(1 + monthlyRate, numberOfPayments) - 1)
        let totalPayment = monthlyPayment * numberOfPayments
        let totalInterest = totalPayment - principal
        
        return .loan(monthlyPayment: monthlyPayment, totalInterest: totalInterest, totalPayment: totalPayment)
    }
    
    func calculateRetirement(currentAge: Int, retirementAge: Int, currentSavings: Double, monthlyContribution: Double, retirementGoal: Double) -> FinancialCalculationResult {
        let yearsToRetirement = retirementAge - currentAge
        let monthsToRetirement = yearsToRetirement * 12
        let monthlyRate = 0.07 / 12 // Assuming 7% annual return
        
        let futureValue = currentSavings * pow(1 + monthlyRate, Double(monthsToRetirement)) + 
                        monthlyContribution * ((pow(1 + monthlyRate, Double(monthsToRetirement)) - 1) / monthlyRate)
        
        let monthlyNeeded = retirementGoal * monthlyRate / (pow(1 + monthlyRate, Double(monthsToRetirement)) - 1)
        let isGoalMet = futureValue >= retirementGoal
        
        return .retirement(projectedSavings: futureValue, monthlyNeeded: monthlyNeeded, isGoalMet: isGoalMet)
    }
    
    func calculateSavings(principal: Double, rate: Double, time: Double, monthlyContribution: Double) -> FinancialCalculationResult {
        let monthlyRate = (rate / 100) / 12
        let months = time * 12
        
        let futureValue = principal * pow(1 + monthlyRate, Double(months)) + 
                        monthlyContribution * ((pow(1 + monthlyRate, Double(months)) - 1) / monthlyRate)
        
        let totalInterest = futureValue - (principal + monthlyContribution * Double(months))
        
        return .savings(futureValue: futureValue, totalInterest: totalInterest)
    }
    
    func calculateMortgage(homePrice: Double, rate: Double, term: Double, downPayment: Double) -> FinancialCalculationResult {
        return calculateLoan(amount: homePrice, rate: rate, term: term, downPayment: downPayment)
    }
    
    func calculateDepreciation(assetValue: Double, rate: Double, usefulLife: Double) -> FinancialCalculationResult {
        let annualDepreciation = assetValue * (rate / 100)
        let bookValue = assetValue - annualDepreciation
        let accumulatedDepreciation = annualDepreciation
        
        return .depreciation(annualDepreciation: annualDepreciation, bookValue: bookValue, accumulatedDepreciation: accumulatedDepreciation)
    }
    
    private func getCompoundingPeriodsPerYear(_ frequency: CompoundFrequency) -> Double {
        switch frequency {
        case .annually: return 1
        case .semiAnnually: return 2
        case .quarterly: return 4
        case .monthly: return 12
        }
    }
}

// MARK: - Supporting Types
enum CompoundFrequency {
    case annually, semiAnnually, quarterly, monthly
}

enum FinancialCalculationResult {
    case investment(futureValue: Double, totalInterest: Double)
    case loan(monthlyPayment: Double, totalInterest: Double, totalPayment: Double)
    case retirement(projectedSavings: Double, monthlyNeeded: Double, isGoalMet: Bool)
    case savings(futureValue: Double, totalInterest: Double)
    case mortgage(monthlyPayment: Double, totalInterest: Double, totalPayment: Double)
    case depreciation(annualDepreciation: Double, bookValue: Double, accumulatedDepreciation: Double)
    
    var principal: Double {
        switch self {
        case .investment(let futureValue, let totalInterest):
            return futureValue - totalInterest
        case .loan(_, _, let totalPayment):
            return totalPayment - (totalInterest + (downPayment ?? 0))
        case .savings(let futureValue, let totalInterest):
            return futureValue - totalInterest
        case .mortgage(_, _, let totalPayment):
            return totalPayment - (totalInterest + (downPayment ?? 0))
        default:
            return 0
        }
    }
    
    var rate: Double {
        return 0.0 // Would be stored in actual implementation
    }
    
    var time: Double {
        return 0.0 // Would be stored in actual implementation
    }
    
    var downPayment: Double? {
        switch self {
        case .loan:
            return 0.0 // Would be stored in actual implementation
        case .mortgage:
            return 0.0 // Would be stored in actual implementation
        default:
            return nil
        }
    }
    
    var currentAge: Int {
        return 0 // Would be stored in actual implementation
    }
    
    var retirementAge: Int {
        return 0 // Would be stored in actual implementation
    }
    
    var monthlyContribution: Double {
        return 0.0 // Would be stored in actual implementation
    }
}
688 lines•27.5 KB
swift

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer