10

The WKInterfaceDevice.current().model property does not give a model number:

For Apple Watch, the value of this string is Apple Watch.

How can the exact Apple Watch model be determined from iOS?

Watch app screenshot, image credits https://support.apple.com/en-us/HT204507

Manuel
  • 14,274
  • 6
  • 57
  • 130

5 Answers5

10

Just slightly updating @Mathieu Vandeginste answer for WatchOS 6 and Apple Watch Series 5.

private func getWatchModel() -> String? {
    var size: size_t = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    return String(cString: &machine, encoding: String.Encoding.utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
}

This needed one change for WatchOS 5 to trim the raw string from getWatchModel() as it now ends in a tab using: ?.trimmingCharacters(in: .whitespacesAndNewlines)

private func getWatchName(model: String) -> String {
    switch model {
        case "Watch1,1":
            return "Apple Watch Series 0 38mm"
        case "Watch1,2":
            return"Apple Watch Series 0 42mm"
        case "Watch2,3":
            return "Apple Watch Series 2 38mm"
        case "Watch2,4":
            return "Apple Watch Series 2 42mmm"
        case "Watch2,6":
            return "Apple Watch Series 1 38mm"
        case "Watch2,7":
            return "Apple Watch Series 1 42mm"
        case "Watch3,1":
            return "Apple Watch Series 3 38mm Cellular"
        case "Watch3,2":
            return "Apple Watch Series 3 42mm Cellular"
        case "Watch3,3":
            return "Apple Watch Series 3 38mm"
        case "Watch3,4":
            return "Apple Watch Series 3 42mm"
        case "Watch4,1":
            return "Apple Watch Series 4 40mm"
        case "Watch4,2":
            return "Apple Watch Series 4 44mm"
        case "Watch4,3":
            return "Apple Watch Series 4 40mm Cellular"
        case "Watch4,4":
            return "Apple Watch Series 4 44mm Cellular"
        case "Watch5,1":
            return "Apple Watch Series 5 40mm"
        case "Watch5,2":
            return "Apple Watch Series 5 44mm"
        case "Watch5,3":
            return "Apple Watch Series 5 40mm Cellular"
        case "Watch5,4":
            return "Apple Watch Series 5 44mm Cellular"
        case "Watch5,9":
            return "Apple Watch SE 40mm"
        case "Watch5,10":
            return "Apple Watch SE 44mm"
        case "Watch5,11":
            return "Apple Watch SE 40mm Cellular"
        case "Watch5,12":
            return "Apple Watch SE 44mm Cellular"
        case "Watch6,1":
            return "Apple Watch Series 6 40mm"
        case "Watch6,2":
            return "Apple Watch Series 6 44mm"
        case "Watch6.3":
            return "Apple Watch Series 6 40mm Cellular"
        case "Watch6,4":
            return "Apple Watch Series 6 44mm Cellular"
        case "Watch6,6":
            return "Apple Watch Series 7 41mm"
        case "Watch6,7":
            return "Apple Watch Series 7 45mm"
        case "Watch6,8":
            return "Apple Watch Series 7 41mm Cellular"
        case "Watch6,9":
            return "Apple Watch Series 7 45mm Cellular"
        default:
            return "unknown"
    }
}

Just added the new models to the above based on this article

liudasbar
  • 173
  • 4
  • 11
Luke
  • 167
  • 2
  • 8
  • This worked for Debug builds but not for Release builds. In release builds the `getWatchModel` function returns `Watc\t` for my Series 3 42mm :(. – itskoBits May 24 '22 at 14:20
5

There is no public API to get that exact information.

You can however use the following (I'll let you translate into Swift):

- (NSString*) modelIdentifier {
    size_t size = 0;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char* machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString* model = [NSString stringWithCString: machine encoding: NSUTF8StringEncoding];
    free(machine);
    return model;
}

This returns a string in the format: "Watch1,1". You'll need to provide a lookup table to do ID -> Name translation.

"Watch1,1" -> Apple Watch 38mm
"Watch1,2" -> Apple Watch 42mm
"Watch2,3" -> Apple Watch Series 2 38mm
"Watch2,4" -> Apple Watch Series 2 42mm
"Watch2,6" -> Apple Watch Series 1 38mm
"Watch2,7" -> Apple Watch Series 1 42mm
"Watch3,1" -> Apple Watch Series 3 38mm Cellular
"Watch3,2" -> Apple Watch Series 3 42mm Cellular
"Watch3,3" -> Apple Watch Series 3 38mm
"Watch3,4" -> Apple Watch Series 3 42mm

By the way, this sysctlbyname API also works for iOS.

Cheers.

appfigurate
  • 136
  • 1
  • Exactly what I’m looking for. Is that using a private API or is it safe for App Store submission? – Manuel Mar 04 '18 at 10:42
  • I should have clarified, I want to determine the Watch model from a method called on iOS (i.e. on the iOS app), not on watchOS. – Manuel Mar 04 '18 at 12:40
  • 3
    Thats a public API - so is app store safe. The code will compile on both iOS and watchOS. On iOS, it'll obviously return the strings "iPhone5,1" etc, and on watchOS it'll return "Watch3,1" etc. If you need to get the watch model from an iOS app, you'll need to get the watch app to send the Model Id across a WCSession to your iOS app. – appfigurate Mar 04 '18 at 19:42
5

EDIT: no longer works for watchOS 4+

This is the Swift 4+ version: working fine for me :)

func getWatchModel() -> String {
    var size: size_t = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = CChar()
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    let model = String(cString: &machine, encoding: String.Encoding.utf8)
    switch model {
    case "Watch1,1":
        return "Apple Watch 28mm"
    case "Watch1,2":
        return"Apple Watch 42mm"
    case "Watch2,3":
        return "Apple Watch Series 2 38mm"
    case "Watch2,4":
        return "Apple Watch Series 2 42mmm"
    case "Watch2,6":
        return "Apple Watch Series 1 38mm"
    case "Watch2,7":
        return "Apple Watch Series 1 42mm"
    case "Watch3,1":
        return "Apple Watch Series 3 38mm Cellular"
    case "Watch3,2":
        return "Apple Watch Series 3 42mm Cellular"
    case "Watch3,3":
        return "Apple Watch Series 3 38mm"
    case "Watch3,4":
        return "Apple Watch Series 3 42mm"
    default:
        return "unknown"
    }
}
Simon Bengtsson
  • 7,573
  • 3
  • 58
  • 87
matmat
  • 73
  • 10
  • This looks like it’s being called from watchOS, but the question was for iOS. – Manuel Apr 18 '18 at 12:56
  • 2
    Yep, the objective-C code does the same. If you run it on iOS you'll have the iPhone Model identifier. What I do is I run this code on my Watch interface, send it to iOS through WatchConnectivity and send it to my analytics. – matmat Apr 19 '18 at 13:44
  • 1
    @Mathieu Vandeginste's answer is correct and on the spot, as the question was about WKInterfaceDevice which is exactly the Watch. – BootMaker Sep 16 '18 at 05:50
  • 4
    This no longer works under watchOS 5. The value of `model` is now "Watc\t" and therefore the overall response from the switch case is always "unknown" – Luke Dec 07 '18 at 12:01
  • Pretty sure there's no 28mm model? (1st case) – David Villegas Sep 02 '20 at 17:33
  • @Luke It appears the buffer needs to be properly allocated in size. Answer here: https://stackoverflow.com/questions/64455391/capture-model-identifier-for-apple-watch-from-watchos/64469707#comment114000490_64469707 – TealShift Oct 21 '20 at 21:08
  • The solution will crash on watchOS 9 / iOS 16 — must implement the size allocation suggested by @TealShift above :) – VincentLoi Sep 10 '22 at 23:18
3

Updated for watchOS 8 and Apple Watch Series 7

Other answers say this doesn't work due to the function returning Watc\t, this fixes that.

public func getWatchModel() -> String? {
    var size: size_t = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    return String(cString: &machine, encoding: String.Encoding.utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
}

public func getWatchName(model: String) -> String {
    switch model {
    case "Watch1,1":
        return "Apple Watch Series 0 38mm"
    case "Watch1,2":
        return"Apple Watch Series 0 42mm"
    case "Watch2,3":
        return "Apple Watch Series 2 38mm"
    case "Watch2,4":
        return "Apple Watch Series 2 42mmm"
    case "Watch2,6":
        return "Apple Watch Series 1 38mm"
    case "Watch2,7":
        return "Apple Watch Series 1 42mm"
    case "Watch3,1":
        return "Apple Watch Series 3 38mm Cellular"
    case "Watch3,2":
        return "Apple Watch Series 3 42mm Cellular"
    case "Watch3,3":
        return "Apple Watch Series 3 38mm"
    case "Watch3,4":
        return "Apple Watch Series 3 42mm"
    case "Watch4,1":
        return "Apple Watch Series 4 40mm"
    case "Watch4,2":
        return "Apple Watch Series 4 44mm"
    case "Watch4,3":
        return "Apple Watch Series 4 40mm Cellular"
    case "Watch4,4":
        return "Apple Watch Series 4 44mm Cellular"
    case "Watch5,1":
        return "Apple Watch Series 5 40mm"
    case "Watch5,2":
        return "Apple Watch Series 5 44mm"
    case "Watch5,3":
        return "Apple Watch Series 5 40mm Cellular"
    case "Watch5,4":
        return "Apple Watch Series 5 44mm Cellular"
    case "Watch5,9":
        return "Apple Watch SE 40mm"
    case "Watch5,10":
        return "Apple Watch SE 44mm"
    case "Watch5,11":
        return "Apple Watch SE 40mm Cellular"
    case "Watch5,12":
        return "Apple Watch SE 44mm Cellular"
    case "Watch6,1":
        return "Apple Watch Series 6 40mm"
    case "Watch6,2":
        return "Apple Watch Series 6 44mm"
    case "Watch6.3":
        return "Apple Watch Series 6 40mm Cellular"
    case "Watch6,4":
        return "Apple Watch Series 6 44mm Cellular"
    case "Watch6,6":
        return "Apple Watch Series 7 41mm"
    case "Watch6,7":
        return "Apple Watch Series 7 45mm"
    case "Watch6,8":
        return "Apple Watch Series 7 41mm Cellular"
    case "Watch6,9":
        return "Apple Watch Series 7 45mm Cellular"
    case "x86_64":
        return "Apple Watch Series 9 Simulator"
    default:
        return "unknown"
    }
}
Will
  • 4,942
  • 2
  • 22
  • 47
1

Updated for watchOS 9 and Series 8/Ultra/SE2

public func getWatchModel() -> String? {
    var size: size_t = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    return String(cString: &machine, encoding: String.Encoding.utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
}
public func getWatchName(model: String) -> String {
    switch model {
    case "Watch1,1":
        return "Apple Watch Series 0 38mm"
    case "Watch1,2":
        return"Apple Watch Series 0 42mm"
    case "Watch2,3":
        return "Apple Watch Series 2 38mm"
    case "Watch2,4":
        return "Apple Watch Series 2 42mmm"
    case "Watch2,6":
        return "Apple Watch Series 1 38mm"
    case "Watch2,7":
        return "Apple Watch Series 1 42mm"
    case "Watch3,1":
        return "Apple Watch Series 3 38mm Cellular"
    case "Watch3,2":
        return "Apple Watch Series 3 42mm Cellular"
    case "Watch3,3":
        return "Apple Watch Series 3 38mm"
    case "Watch3,4":
        return "Apple Watch Series 3 42mm"
    case "Watch4,1":
        return "Apple Watch Series 4 40mm"
    case "Watch4,2":
        return "Apple Watch Series 4 44mm"
    case "Watch4,3":
        return "Apple Watch Series 4 40mm Cellular"
    case "Watch4,4":
        return "Apple Watch Series 4 44mm Cellular"
    case "Watch5,1":
        return "Apple Watch Series 5 40mm"
    case "Watch5,2":
        return "Apple Watch Series 5 44mm"
    case "Watch5,3":
        return "Apple Watch Series 5 40mm Cellular"
    case "Watch5,4":
        return "Apple Watch Series 5 44mm Cellular"
    case "Watch5,9":
        return "Apple Watch SE 40mm"
    case "Watch5,10":
        return "Apple Watch SE 44mm"
    case "Watch5,11":
        return "Apple Watch SE 40mm Cellular"
    case "Watch5,12":
        return "Apple Watch SE 44mm Cellular"
    case "Watch6,1":
        return "Apple Watch Series 6 40mm"
    case "Watch6,2":
        return "Apple Watch Series 6 44mm"
    case "Watch6,3":
        return "Apple Watch Series 6 40mm Cellular"
    case "Watch6,4":
        return "Apple Watch Series 6 44mm Cellular"
    case "Watch6,6":
        return "Apple Watch Series 7 41mm"
    case "Watch6,7":
        return "Apple Watch Series 7 45mm"
    case "Watch6,8":
        return "Apple Watch Series 7 41mm Cellular"
        fallthrough
    case "Watch6,9":
        return "Apple Watch Series 7 45mm Cellular"
    case "Watch6,10":
        return "Apple Watch SE 2 40mm"
    case "Watch6,11":
        return "Apple Watch SE 2 44mm"
    case "Watch6,12":
        return "Apple Watch SE 2 40mm Cellular"
    case "Watch6,13":
        return "Apple Watch SE 2 44mm Cellular"
    case "Watch6,14":
        return "Apple Watch Series 8 41mm"
    case "Watch6,15":
        return "Apple Watch Series 8 45mm"
    case "Watch6,16":
        return "Apple Watch Series 8 41mm Cellular"
    case "Watch6,17":
        return "Apple Watch Series 8 45mm Cellular"
    case "Watch6,18":
        return "Apple Watch Ultra"
    case "x86_64":
        return "Apple Watch Series 9 Simulator"
    default:
        return "unknown"
    }
}
C. aVE
  • 11
  • 3