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
  • 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
WatchCalculatorViewController.swift
WatchCalculatorViewController.swift
Raw Download
Find: Go to:
//
//  WatchCalculatorViewController.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 WatchKit
import Foundation

class WatchCalculatorViewController: WKInterfaceController {
    
    // MARK: - Outlets
    @IBOutlet weak var displayLabel: WKInterfaceLabel!
    @IBOutlet weak var operationLabel: WKInterfaceLabel!
    
    // Button outlets for different button groups
    @IBOutlet weak var button0: WKInterfaceButton!
    @IBOutlet weak var button1: WKInterfaceButton!
    @IBOutlet weak var button2: WKInterfaceButton!
    @IBOutlet weak var button3: WKInterfaceButton!
    @IBOutlet weak var button4: WKInterfaceButton!
    @IBOutlet weak var button5: WKInterfaceButton!
    @IBOutlet weak var button6: WKInterfaceButton!
    @IBOutlet weak var button7: WKInterfaceButton!
    @IBOutlet weak var button8: WKInterfaceButton!
    @IBOutlet weak var button9: WKInterfaceButton!
    
    @IBOutlet weak var buttonDecimal: WKInterfaceButton!
    @IBOutlet weak var buttonClear: WKInterfaceButton!
    @IBOutlet weak var buttonDelete: WKInterfaceButton!
    
    @IBOutlet weak var buttonAdd: WKInterfaceButton!
    @IBOutlet weak var buttonSubtract: WKInterfaceButton!
    @IBOutlet weak var buttonMultiply: WKInterfaceButton!
    @IBOutlet weak var buttonDivide: WKInterfaceButton!
    @IBOutlet weak var buttonEquals: WKInterfaceButton!
    
    // MARK: - Properties
    private var currentValue: String = "0"
    private var previousValue: Double = 0
    private var operation: String?
    private var shouldResetDisplay = false
    
    // MARK: - Lifecycle
    override func awake(withContext context: Any?) {
        super.awake(withContext: context)
        setupUI()
        updateDisplay()
    }
    
    override func willActivate() {
        super.willActivate()
        // Sync with iPhone app if needed
        syncWithPhone()
    }
    
    // MARK: - Setup
    private func setupUI() {
        // Set initial display
        displayLabel.setText("0")
        operationLabel.setText("")
        
        // Configure button colors based on theme
        configureButtonColors()
    }
    
    private func configureButtonColors() {
        // Use system colors for better watch compatibility
        let numberColor = UIColor.darkGray
        let operationColor = UIColor.systemOrange
        let functionColor = UIColor.systemBlue
        
        // Number buttons
        [button0, button1, button2, button3, button4, button5, button6, button7, button8, button9].forEach { button in
            button?.setBackgroundColor(numberColor)
        }
        
        // Operation buttons
        [buttonAdd, buttonSubtract, buttonMultiply, buttonDivide, buttonEquals].forEach { button in
            button?.setBackgroundColor(operationColor)
        }
        
        // Function buttons
        [buttonClear, buttonDelete, buttonDecimal].forEach { button in
            button?.setBackgroundColor(functionColor)
        }
    }
    
    private func syncWithPhone() {
        // Sync calculation history and settings with iPhone app
        if let sharedDefaults = UserDefaults(suiteName: "group.com.rskworld.calculator") {
            if let lastValue = sharedDefaults.string(forKey: "LastCalculationValue") {
                currentValue = lastValue
                updateDisplay()
            }
        }
    }
    
    // MARK: - Actions
    @IBAction func numberButtonTapped(_ sender: WKInterfaceButton) {
        guard let title = sender.title else { return }
        
        if shouldResetDisplay {
            currentValue = "0"
            shouldResetDisplay = false
        }
        
        if currentValue == "0" {
            currentValue = title
        } else if currentValue.count < 9 { // Limit display length for watch
            currentValue += title
        }
        
        updateDisplay()
        provideHapticFeedback()
    }
    
    @IBAction func decimalButtonTapped(_ sender: WKInterfaceButton) {
        if shouldResetDisplay {
            currentValue = "0"
            shouldResetDisplay = false
        }
        
        if !currentValue.contains(".") {
            currentValue += "."
        }
        
        updateDisplay()
        provideHapticFeedback()
    }
    
    @IBAction func operationButtonTapped(_ sender: WKInterfaceButton) {
        guard let title = sender.title else { return }
        
        if let currentOperation = operation {
            // Perform previous operation
            performCalculation()
        } else {
            previousValue = Double(currentValue) ?? 0
        }
        
        operation = title
        operationLabel.setText(title)
        shouldResetDisplay = true
        provideHapticFeedback()
    }
    
    @IBAction func equalsButtonTapped(_ sender: WKInterfaceButton) {
        if operation != nil {
            performCalculation()
            operation = nil
            operationLabel.setText("")
        }
        provideHapticFeedback()
    }
    
    @IBAction func clearButtonTapped(_ sender: WKInterfaceButton) {
        currentValue = "0"
        previousValue = 0
        operation = nil
        operationLabel.setText("")
        shouldResetDisplay = false
        updateDisplay()
        provideHapticFeedback()
    }
    
    @IBAction func deleteButtonTapped(_ sender: WKInterfaceButton) {
        if currentValue.count > 1 {
            currentValue.removeLast()
        } else {
            currentValue = "0"
        }
        updateDisplay()
        provideHapticFeedback()
    }
    
    // MARK: - Methods
    private func performCalculation() {
        guard let operation = operation,
              let currentValueDouble = Double(currentValue) else { return }
        
        var result: Double = 0
        
        switch operation {
        case "+":
            result = previousValue + currentValueDouble
        case "-":
            result = previousValue - currentValueDouble
        case "×":
            result = previousValue * currentValueDouble
        case "÷":
            result = currentValueDouble != 0 ? previousValue / currentValueDouble : 0
        default:
            return
        }
        
        currentValue = formatResult(result)
        updateDisplay()
        
        // Save to shared defaults for sync with iPhone
        saveToSharedDefaults(result)
    }
    
    private func formatResult(_ result: Double) -> String {
        if result.truncatingRemainder(dividingBy: 1) == 0 {
            return String(Int(result))
        } else {
            return String(format: "%.6f", result).trimmingCharacters(in: .trailingZeros)
        }
    }
    
    private func updateDisplay() {
        displayLabel.setText(currentValue)
    }
    
    private func provideHapticFeedback() {
        WKInterfaceDevice.current().play(.click)
    }
    
    private func saveToSharedDefaults(_ result: Double) {
        if let sharedDefaults = UserDefaults(suiteName: "group.com.rskworld.calculator") {
            sharedDefaults.set(currentValue, forKey: "LastCalculationValue")
            sharedDefaults.set(Date(), forKey: "LastCalculationDate")
            
            // Add to history
            var history = sharedDefaults.stringArray(forKey: "CalculationHistory") ?? []
            let calculation = "\(previousValue) \(operation ?? "") \(Double(currentValue) ?? 0) = \(result)"
            history.append(calculation)
            
            // Keep only last 50 calculations
            if history.count > 50 {
                history.removeFirst(history.count - 50)
            }
            
            sharedDefaults.set(history, forKey: "CalculationHistory")
        }
    }
}

// MARK: - Scientific Calculator for Watch
class WatchScientificCalculatorViewController: WKInterfaceController {
    
    @IBOutlet weak var displayLabel: WKInterfaceLabel!
    @IBOutlet weak var modeLabel: WKInterfaceLabel!
    
    private var currentValue: String = "0"
    private var angleMode: AngleMode = .degrees
    
    enum AngleMode: String, CaseIterable {
        case degrees = "DEG"
        case radians = "RAD"
    }
    
    override func awake(withContext context: Any?) {
        super.awake(withContext: context)
        setupUI()
    }
    
    private func setupUI() {
        displayLabel.setText("0")
        modeLabel.setText(angleMode.rawValue)
    }
    
    @IBAction func scientificFunctionTapped(_ sender: WKInterfaceButton) {
        guard let title = sender.title else { return }
        
        let value = Double(currentValue) ?? 0
        var result: Double = 0
        
        switch title {
        case "sin":
            result = sin(angleMode == .degrees ? value * .pi / 180 : value)
        case "cos":
            result = cos(angleMode == .degrees ? value * .pi / 180 : value)
        case "tan":
            result = tan(angleMode == .degrees ? value * .pi / 180 : value)
        case "x²":
            result = value * value
        case "√":
            result = sqrt(value)
        case "log":
            result = log10(value)
        case "ln":
            result = log(value)
        case "π":
            result = .pi
        case "e":
            result = .e
        default:
            return
        }
        
        currentValue = formatResult(result)
        displayLabel.setText(currentValue)
        WKInterfaceDevice.current().play(.click)
    }
    
    @IBAction func toggleAngleMode(_ sender: WKInterfaceButton) {
        angleMode = angleMode == .degrees ? .radians : .degrees
        modeLabel.setText(angleMode.rawValue)
        WKInterfaceDevice.current().play(.click)
    }
    
    private func formatResult(_ result: Double) -> String {
        if result.truncatingRemainder(dividingBy: 1) == 0 {
            return String(Int(result))
        } else {
            return String(format: "%.6f", result).trimmingCharacters(in: .trailingZeros)
        }
    }
}

// MARK: - Unit Converter for Watch
class WatchUnitConverterViewController: WKInterfaceController {
    
    @IBOutlet weak var fromValueLabel: WKInterfaceLabel!
    @IBOutlet weak var fromUnitLabel: WKInterfaceLabel!
    @IBOutlet weak var toValueLabel: WKInterfaceLabel!
    @IBOutlet weak var toUnitLabel: WKInterfaceLabel!
    
    private var currentValue: Double = 1.0
    private var currentCategory: String = "Length"
    private var fromUnit: String = "Meter"
    private var toUnit: String = "Foot"
    
    override func awake(withContext context: Any?) {
        super.awake(withContext: context)
        setupUI()
        performConversion()
    }
    
    private func setupUI() {
        fromValueLabel.setText("1.0")
        fromUnitLabel.setText("Meter")
        toValueLabel.setText("3.28")
        toUnitLabel.setText("Foot")
    }
    
    @IBAction func categoryChanged(_ sender: WKInterfaceButton) {
        // Cycle through categories
        let categories = ["Length", "Weight", "Temperature"]
        if let currentIndex = categories.firstIndex(of: currentCategory) {
            let nextIndex = (currentIndex + 1) % categories.count
            currentCategory = categories[nextIndex]
        }
        
        updateUnitsForCategory()
        performConversion()
    }
    
    @IBAction func swapUnits(_ sender: WKInterfaceButton) {
        let temp = fromUnit
        fromUnit = toUnit
        toUnit = temp
        
        fromUnitLabel.setText(fromUnit)
        toUnitLabel.setText(toUnit)
        
        performConversion()
    }
    
    @IBAction func adjustValue(_ sender: WKInterfaceButton) {
        guard let title = sender.title else { return }
        
        switch title {
        case "+":
            currentValue += 1
        case "-":
            currentValue = max(0, currentValue - 1)
        case "×10":
            currentValue *= 10
        case "÷10":
            currentValue /= 10
        default:
            return
        }
        
        fromValueLabel.setText(String(format: "%.2f", currentValue))
        performConversion()
    }
    
    private func updateUnitsForCategory() {
        switch currentCategory {
        case "Length":
            fromUnit = "Meter"
            toUnit = "Foot"
        case "Weight":
            fromUnit = "Kilogram"
            toUnit = "Pound"
        case "Temperature":
            fromUnit = "Celsius"
            toUnit = "Fahrenheit"
        default:
            break
        }
        
        fromUnitLabel.setText(fromUnit)
        toUnitLabel.setText(toUnit)
    }
    
    private func performConversion() {
        let result: Double
        
        switch currentCategory {
        case "Length":
            result = currentValue * 3.28084 // Meter to Foot
        case "Weight":
            result = currentValue * 2.20462 // Kilogram to Pound
        case "Temperature":
            result = currentValue * 9/5 + 32 // Celsius to Fahrenheit
        default:
            result = currentValue
        }
        
        toValueLabel.setText(String(format: "%.2f", result))
    }
}

// MARK: - Complication Controller
class CalculatorComplicationController: NSObject, CLKComplicationDataSource {
    
    func complicationDescriptors() -> [CLKComplicationDescriptor] {
        return [
            CLKComplicationDescriptor(identifier: "calculator", displayName: "Calculator", supportedFamilies: [.circularSmall, .modularSmall, .utilitarianSmall])
        ]
    }
    
    func handleSharedComplicationDescriptors(_ complicationDescriptors: [CLKComplicationDescriptor]) {
        // Handle shared complications
    }
    
    func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
        let entry = createTimelineEntry(for: complication)
        handler(entry)
    }
    
    private func createTimelineEntry(for complication: CLKComplication) -> CLKComplicationTimelineEntry {
        let date = Date()
        
        switch complication.family {
        case .circularSmall:
            let template = CLKComplicationTemplateCircularSmallSimpleText()
            template.textProvider = CLKSimpleTextProvider(text: "123")
            return CLKComplicationTimelineEntry(date: date, complicationTemplate: template)
            
        case .modularSmall:
            let template = CLKComplicationTemplateModularSmallSimpleText()
            template.textProvider = CLKSimpleTextProvider(text: "456")
            return CLKComplicationTimelineEntry(date: date, complicationTemplate: template)
            
        case .utilitarianSmall:
            let template = CLKComplicationTemplateUtilitarianSmallSimpleText()
            template.textProvider = CLKSimpleTextProvider(text: "789")
            return CLKComplicationTimelineEntry(date: date, complicationTemplate: template)
            
        default:
            fatalError("Unsupported complication family")
        }
    }
}
469 lines•15.3 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