8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

リフレクションを使わずにデバイスモデル名を取得する方法(Swift)

Last updated at Posted at 2023-08-03

はじめに

iPhone6,1 のようなデバイスモデル名を取得したいことがありますが、ググってもリフレクションを使った記事しか見つかりません。
Twitterでリフレクションを使わずに取得する方法を教えていただいた ので紹介します。

環境

  • OS:macOS Ventura 13.4.1
  • Swift:5.8

デバイスモデル名を取得する方法

デバイスモデル名を取得する方法です。

リフレクションあり

まずはリフレクションを使う方法です。

以下の記事を参考に実装します。

UIDevice+Model.swift
import UIKit

extension UIDevice {
    static var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)

        let mirror = Mirror(reflecting: systemInfo.machine)
        let identifier = mirror.children.reduce("") { identifier, element in
            guard
                let value = element.value as? Int8,
                value != 0
            else {
                return identifier
            }

            return identifier + String(UnicodeScalar(UInt8(value)))
        }

        return identifier
    }
}

実際に呼び出せることを確認します。

print("Device model: \(UIDevice.modelName)")

無事にデバイスモデル名が出力されました。

Device model: arm64

Swift Playgroundsで実行したため arm64 と出力されています。

リフレクションなし

次にリフレクションを使わずに実装します。

UIDevice+Model.swift
import UIKit

extension UIDevice {
    static var modelName: String {
        var systemInfo = utsname()
        uname(&systemInfo)

        let chars: [CChar] = [
            systemInfo.machine.0,
            systemInfo.machine.1,
            systemInfo.machine.2,
            systemInfo.machine.3,
            systemInfo.machine.4,
            systemInfo.machine.5,
            systemInfo.machine.6,
            systemInfo.machine.7,
            systemInfo.machine.8,
            systemInfo.machine.9,
            systemInfo.machine.10,
            systemInfo.machine.11,
            systemInfo.machine.12,
            systemInfo.machine.13,
            systemInfo.machine.14,
            systemInfo.machine.15,
            systemInfo.machine.16,
            systemInfo.machine.17,
            systemInfo.machine.18,
            systemInfo.machine.19,
            systemInfo.machine.20,
            systemInfo.machine.21,
            systemInfo.machine.22,
            systemInfo.machine.23,
            systemInfo.machine.24,
            systemInfo.machine.25,
            systemInfo.machine.26,
            systemInfo.machine.27,
            systemInfo.machine.28,
            systemInfo.machine.29,
            systemInfo.machine.30,
            systemInfo.machine.31,
            systemInfo.machine.32,
            systemInfo.machine.33,
            systemInfo.machine.34,
            systemInfo.machine.35,
            systemInfo.machine.36,
            systemInfo.machine.37,
            systemInfo.machine.38,
            systemInfo.machine.39,
            systemInfo.machine.40,
            systemInfo.machine.41,
            systemInfo.machine.42,
            systemInfo.machine.43,
            systemInfo.machine.44,
            systemInfo.machine.45,
            systemInfo.machine.46,
            systemInfo.machine.47,
            systemInfo.machine.48,
            systemInfo.machine.49,
            systemInfo.machine.50,
            systemInfo.machine.51,
            systemInfo.machine.52,
            systemInfo.machine.53,
            systemInfo.machine.54,
            systemInfo.machine.55,
            systemInfo.machine.56,
            systemInfo.machine.57,
            systemInfo.machine.58,
            systemInfo.machine.59,
            systemInfo.machine.60,
            systemInfo.machine.61,
            systemInfo.machine.62,
            systemInfo.machine.63,
            systemInfo.machine.64,
            systemInfo.machine.65,
            systemInfo.machine.66,
            systemInfo.machine.67,
            systemInfo.machine.68,
            systemInfo.machine.69,
            systemInfo.machine.70,
            systemInfo.machine.71,
            systemInfo.machine.72,
            systemInfo.machine.73,
            systemInfo.machine.74,
            systemInfo.machine.75,
            systemInfo.machine.76,
            systemInfo.machine.77,
            systemInfo.machine.78,
            systemInfo.machine.79,
            systemInfo.machine.80,
            systemInfo.machine.81,
            systemInfo.machine.82,
            systemInfo.machine.83,
            systemInfo.machine.84,
            systemInfo.machine.85,
            systemInfo.machine.86,
            systemInfo.machine.87,
            systemInfo.machine.88,
            systemInfo.machine.89,
            systemInfo.machine.90,
            systemInfo.machine.91,
            systemInfo.machine.92,
            systemInfo.machine.93,
            systemInfo.machine.94,
            systemInfo.machine.95,
            systemInfo.machine.96,
            systemInfo.machine.97,
            systemInfo.machine.98,
            systemInfo.machine.99,
            systemInfo.machine.100,
            systemInfo.machine.101,
            systemInfo.machine.102,
            systemInfo.machine.103,
            systemInfo.machine.104,
            systemInfo.machine.105,
            systemInfo.machine.106,
            systemInfo.machine.107,
            systemInfo.machine.108,
            systemInfo.machine.109,
            systemInfo.machine.110,
            systemInfo.machine.111,
            systemInfo.machine.112,
            systemInfo.machine.113,
            systemInfo.machine.114,
            systemInfo.machine.115,
            systemInfo.machine.116,
            systemInfo.machine.117,
            systemInfo.machine.118,
            systemInfo.machine.119,
            systemInfo.machine.120,
            systemInfo.machine.121,
            systemInfo.machine.122,
            systemInfo.machine.123,
            systemInfo.machine.124,
            systemInfo.machine.125,
            systemInfo.machine.126,
            systemInfo.machine.127,
            systemInfo.machine.128,
            systemInfo.machine.129,
            systemInfo.machine.130,
            systemInfo.machine.131,
            systemInfo.machine.132,
            systemInfo.machine.133,
            systemInfo.machine.134,
            systemInfo.machine.135,
            systemInfo.machine.136,
            systemInfo.machine.137,
            systemInfo.machine.138,
            systemInfo.machine.139,
            systemInfo.machine.140,
            systemInfo.machine.141,
            systemInfo.machine.142,
            systemInfo.machine.143,
            systemInfo.machine.144,
            systemInfo.machine.145,
            systemInfo.machine.146,
            systemInfo.machine.147,
            systemInfo.machine.148,
            systemInfo.machine.149,
            systemInfo.machine.150,
            systemInfo.machine.151,
            systemInfo.machine.152,
            systemInfo.machine.153,
            systemInfo.machine.154,
            systemInfo.machine.155,
            systemInfo.machine.156,
            systemInfo.machine.157,
            systemInfo.machine.158,
            systemInfo.machine.159,
            systemInfo.machine.160,
            systemInfo.machine.161,
            systemInfo.machine.162,
            systemInfo.machine.163,
            systemInfo.machine.164,
            systemInfo.machine.165,
            systemInfo.machine.166,
            systemInfo.machine.167,
            systemInfo.machine.168,
            systemInfo.machine.169,
            systemInfo.machine.170,
            systemInfo.machine.171,
            systemInfo.machine.172,
            systemInfo.machine.173,
            systemInfo.machine.174,
            systemInfo.machine.175,
            systemInfo.machine.176,
            systemInfo.machine.177,
            systemInfo.machine.178,
            systemInfo.machine.179,
            systemInfo.machine.180,
            systemInfo.machine.181,
            systemInfo.machine.182,
            systemInfo.machine.183,
            systemInfo.machine.184,
            systemInfo.machine.185,
            systemInfo.machine.186,
            systemInfo.machine.187,
            systemInfo.machine.188,
            systemInfo.machine.189,
            systemInfo.machine.190,
            systemInfo.machine.191,
            systemInfo.machine.192,
            systemInfo.machine.193,
            systemInfo.machine.194,
            systemInfo.machine.195,
            systemInfo.machine.196,
            systemInfo.machine.197,
            systemInfo.machine.198,
            systemInfo.machine.199,
            systemInfo.machine.200,
            systemInfo.machine.201,
            systemInfo.machine.202,
            systemInfo.machine.203,
            systemInfo.machine.204,
            systemInfo.machine.205,
            systemInfo.machine.206,
            systemInfo.machine.207,
            systemInfo.machine.208,
            systemInfo.machine.209,
            systemInfo.machine.210,
            systemInfo.machine.211,
            systemInfo.machine.212,
            systemInfo.machine.213,
            systemInfo.machine.214,
            systemInfo.machine.215,
            systemInfo.machine.216,
            systemInfo.machine.217,
            systemInfo.machine.218,
            systemInfo.machine.219,
            systemInfo.machine.220,
            systemInfo.machine.221,
            systemInfo.machine.222,
            systemInfo.machine.223,
            systemInfo.machine.224,
            systemInfo.machine.225,
            systemInfo.machine.226,
            systemInfo.machine.227,
            systemInfo.machine.228,
            systemInfo.machine.229,
            systemInfo.machine.230,
            systemInfo.machine.231,
            systemInfo.machine.232,
            systemInfo.machine.233,
            systemInfo.machine.234,
            systemInfo.machine.235,
            systemInfo.machine.236,
            systemInfo.machine.237,
            systemInfo.machine.238,
            systemInfo.machine.239,
            systemInfo.machine.240,
            systemInfo.machine.241,
            systemInfo.machine.242,
            systemInfo.machine.243,
            systemInfo.machine.244,
            systemInfo.machine.245,
            systemInfo.machine.246,
            systemInfo.machine.247,
            systemInfo.machine.248,
            systemInfo.machine.249,
            systemInfo.machine.250,
            systemInfo.machine.251,
            systemInfo.machine.252,
            systemInfo.machine.253,
            systemInfo.machine.254,
            systemInfo.machine.255,
            systemInfo.machine.254,
            systemInfo.machine.255,
        ]

        return String(cString: chars)
    }
}

愚直ですが、実際に呼び出せます。

print("Device model: \(UIDevice.modelName)") // Device model: arm64

解説

まず systemInfo.machine は256つの要素を持ったタプルです。

Darwin.POSIX.sys.utsname
public struct utsname {
    // ...
    public var machine: (CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar, CChar) /* [XSI] Hardware type */
}

タプルは .x でx番目の要素へアクセスできるため、 systemInfo.machine.x と書いていました。
そして String への変換はタプルでなく配列で CChar を用意する必要があるため、愚直にタプルの要素を1つずつ配列へ格納していた、ということです。

余談

systemInfo.machine.x は1文字ずつに対応しているので、 arm64 なら chars の中身が systemInfo.machine.5 まででも問題なく実行できます。

let chars: [CChar] = [
    systemInfo.machine.0,
    systemInfo.machine.1,
    systemInfo.machine.2,
    systemInfo.machine.3,
    systemInfo.machine.4,
    systemInfo.machine.5,
]

では配列の中身が以下ならどう出力されるでしょうか。

let chars: [CChar] = [
    systemInfo.machine.1,
    systemInfo.machine.2,
    systemInfo.machine.4,
    systemInfo.machine.5,
]

答えは以下です。

print("Device model: \(UIDevice.modelName)") // Device model: rm4

1(0)番目の a と4(3)番目の 6 が抜けてしまいました。

表にするとわかりやすいです。

変数 文字
systemInfo.machine.0 97 a
systemInfo.machine.1 114 r
systemInfo.machine.2 109 m
systemInfo.machine.3 54 6
systemInfo.machine.4 52 4
systemInfo.machine.5systemInfo.machine.255 0 NULL

あとは終端がNULL( 0 )でないと実行時エラーが発生します。

let chars: [CChar] = [
    systemInfo.machine.1,
    systemInfo.machine.2,
    systemInfo.machine.4,
]

// ❌: Input of String.init(cString:) must be null-terminated
return String(cString: chars)

最初の例は systemInfo.machine.50 なので成功しました。
終端は systemInfo.machine.6 でも 0 でも .init() でも問題ありません。

let chars: [CChar] = [
    systemInfo.machine.1,
    systemInfo.machine.2,
    systemInfo.machine.4,
    systemInfo.machine.5, // `systemInfo.machine.6` や `0` 、 `.init()` などでもOK
]

おわりに

リフレクションを多用するのはよくないですが、タプルを配列へ変換するのに便利ということがわかりました。
リフレクションは用法・用量を守って使っていきたいと思います。

8
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?