Как импортировать <sys/utsname.h> в swift

Я создаю проект в Swift. Я хочу отобразить modelName. Я следую ниже ссылки, чтобы получить имя модели

http://myiosdevelopment.blogspot.co.uk/2012/11/getting-device-model-number-whether-its.html

Код в ссылке написан в objective-c. Но я не уверен, как импортировать это в Swift.

#import <sys/utsname.h>

Пожалуйста, помогите кому-нибудь помочь

Ответ 1

sys/utsname.h импортируется в Swift по умолчанию, поэтому вам действительно не нужно импортировать его из заголовка моста. Но использование utsname из Swift действительно болезненно, хотя Swift импортирует фиксированную длину массива C как кортежи. Если вы посмотрите на utsname.h, вы увидите, что члены utsname из C struct - это все char массив из 256 length:

#define _SYS_NAMELEN    256

struct  utsname {
    char    sysname[_SYS_NAMELEN];  /* [XSI] Name of OS */
    char    nodename[_SYS_NAMELEN]; /* [XSI] Name of this network node */
    char    release[_SYS_NAMELEN];  /* [XSI] Release level */
    char    version[_SYS_NAMELEN];  /* [XSI] Version level */
    char    machine[_SYS_NAMELEN];  /* [XSI] Hardware type */
};

который импортируется в Swift следующим образом:

var _SYS_NAMELEN: Int32 { get }

struct utsname {
    var sysname: (Int8, Int8, /* ... 254 more times "Int8, " here ... */) /* [XSI] Name of OS */
    var nodename: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Name of this network node */
    var release: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Release level */
    var version: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Version level */
    var machine: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Hardware type */
}

Да, это кортежи с 256 Int8 s. В каких случаях эта веселая автозаполнение в Xcode:

Xcode completion of <code>utsname</code> initializer

В настоящее время нет способа инициализировать кортеж в Swift без выписывания всего значения, поэтому инициализация его как локальной переменной будет довольно многословной, как вы видите выше. Также нет способа преобразовать кортеж в массив, так что огромный кортеж также не очень полезен.

Самое простое решение - реализовать его в Objective-C.

Если вы настроены на использование Swift, вы можете сделать это, но это не очень хорошо:

// Declare an array that can hold the bytes required to store `utsname`, initilized
// with zeros. We do this to get a chunk of memory that is freed upon return of
// the method
var sysInfo: [CChar] = Array(count: sizeof(utsname), repeatedValue: 0)

// We need to get to the underlying memory of the array:
let machine = sysInfo.withUnsafeMutableBufferPointer { (inout ptr: UnsafeMutableBufferPointer<CChar>) -> String in
    // Call uname and let it write into the memory Swift allocated for the array
    uname(UnsafeMutablePointer<utsname>(ptr.baseAddress))

    // Now here is the ugly part: `machine` is the 5th member of `utsname` and
    // each member member is `_SYS_NAMELEN` sized. We skip the the first 4 members
    // of the struct which will land us at the memory address of the `machine`
    // member
    let machinePtr = advance(ptr.baseAddress, Int(_SYS_NAMELEN * 4))

    // Create a Swift string from the C string
    return String.fromCString(machinePtr)!
}

Ответ 2

Код, показанный в этом сообщении блога, выглядит как C, а не Objective C - однако я думаю, что вы можете написать обертку вокруг этого в Objective-C

Чтобы включить мост между Objective-C и быстрым, просто добавьте в проект новый файл Objective-C - Xcode предложит вам создать заголовок моста

enter image description here

Просто ответьте да, и Xcode автоматически создаст файл <appname>-Bridging-Header.h. Откройте его и #include любой заголовочный файл Objective-C, который вы хотите использовать из swift.

Ответ 3

В быстрой версии 2.0:

var sysInfo: [CChar] = Array(count: sizeof(utsname), repeatedValue: 0)
let deviceModel = sysInfo.withUnsafeMutableBufferPointer { (inout ptr: UnsafeMutableBufferPointer<CChar>) -> String in
        uname(UnsafeMutablePointer<utsname>(ptr.baseAddress))
        let machinePtr = ptr.baseAddress.advancedBy(Int(_SYS_NAMELEN * 4))
        return String.fromCString(machinePtr)!
}
print(deviceModel)

Ответ 4

В Swift 4 вы можете просто использовать свойство модели UIDevice:

func getPhoneModel() -> String { return UIDevice.current.model }