I am creating a project in Swift. I want to display the modelName. I am following below link to get the modelName
http://myiosdevelopment.blogspot.co.uk/2012/11/getting-device-model-number-whether-its.html
The code in the link is written in objective-c. But I am not sure how to import this in Swift.
#import <sys/utsname.h>
Please someone help
sys/utsname.h
is imported into Swift by default, so you don't really need to import it from the bridging header. But using utsname
from Swift is really painful though, as Swift imports fixed length C array as tuples. If you look into utsname.h
, you see that the C struct
members of utsname
are all char
array of 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 */
};
Which gets imported into Swift like this:
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 */
}
Yes, they're tuples with 256 Int8
s. Which cases this hilarious autocompletion in Xcode:
Currently, there is no way to initialize an tuple in Swift without writing out all value, so initializing it as a local variable would be rather verbose, as you see above. There is also no way to convert the tuple to an array, so that huge tuple is also not very useful.
The easiest solution would be to implement it in Objective-C.
If you're dead set on using Swift, you can do this, but it's not pretty:
// 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)!
}
In Swift 4 you can just use the UIDevice model property:
func getPhoneModel() -> String {
return UIDevice.current.model
}
my 2 cents for Swift 5 if You want to call utsname:
func platform() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let size = Int(_SYS_NAMELEN) // is 32, but posix AND its init is 256....
let s = withUnsafeMutablePointer(to: &systemInfo.machine) {p in
p.withMemoryRebound(to: CChar.self, capacity: size, {p2 in
return String(cString: p2)
})
}
return s
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With