使用iOS SDK和完整的Cocoa Touch/Objective-C代码确定用户设备

8

我根据不同的来源编写了以下UIDevice类别。我升级了platformCode方法,使其比现有的低级。

这个代码完美地工作,但platformCode方法很低级。您知道是否可以用Cocoa Touch代码替换这种调用吗?以下是相关代码:

UIDevice_enhanced.h

@interface UIDevice (Enhanced)

typedef enum {
    kUnknownPlatform = 0,
    kiPhone1G,
    kiPhone3G,
    kiPhone3GS,
    kiPhone4,
    kiPhone4Verizon,
    kiPhone4S,
    kiPodTouch1G,
    kiPodTouch2G,
    kiPodTouch3G,
    kiPodTouch4G,
    kiPad,
    kiPad2Wifi,
    kiPad2GSM,
    kiPad2CMDA,
    kSimulator
} PlatformType;

- (NSString *) platformName;
- (PlatformType) platform;

@end

UIDevice_enhanced.m

#import "UIDevice_enhanced.h"
#include <sys/utsname.h>

@interface UIDevice (Enhanced)
- (NSString *) platformCode;
@end 


@implementation UIDevice (Enhanced)

// Utility method (private)
- (NSString*) platformCode {
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString* platform =  [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];

    return platform;
}

// Public method to use
- (NSString*) platformName {
    NSString* platform = [self platformCode];

    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone 1G";
    if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,2"])    return @"Verizon iPhone 4";
    if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([platform isEqualToString:@"iPod1,1"])      return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"])      return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"])      return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"])      return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([platform isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([platform isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([platform isEqualToString:@"i386"])         return @"Simulator";

    return platform;
}

// Public method to use
- (PlatformType) platform {
    NSString *platform = [self platformCode];
    if ([platform isEqualToString:@"iPhone1,1"])    return kiPhone1G;
    if ([platform isEqualToString:@"iPhone1,2"])    return kiPhone3G;
    if ([platform isEqualToString:@"iPhone2,1"])    return kiPhone3GS;
    if ([platform isEqualToString:@"iPhone3,1"])    return kiPhone4;
    if ([platform isEqualToString:@"iPhone3,2"])    return kiPhone4Verizon;
    if ([platform isEqualToString:@"iPhone4,1"])    return kiPhone4S;
    if ([platform isEqualToString:@"iPod1,1"])      return kiPodTouch1G;
    if ([platform isEqualToString:@"iPod2,1"])      return kiPodTouch2G;
    if ([platform isEqualToString:@"iPod3,1"])      return kiPodTouch3G;
    if ([platform isEqualToString:@"iPod4,1"])      return kiPodTouch4G;
    if ([platform isEqualToString:@"iPad1,1"])      return kiPad;
    if ([platform isEqualToString:@"iPad2,1"])      return kiPad2Wifi;
    if ([platform isEqualToString:@"iPad2,2"])      return kiPad2GSM;
    if ([platform isEqualToString:@"iPad2,3"])      return kiPad2CMDA;
    if ([platform isEqualToString:@"i386"])         return kSimulator;

    return kUnknownPlatform;
}

@end

这是完全有效的Objective-C代码(就像所有C代码一样),它也不太低级(我建议对于有限的多选集使用枚举而不是字符串)。 - user529758
2个回答

2
这可以被视为一种“Objective-C”的方法来完成它:
// Utility method (private)
- (NSString *)platformCode {
    // This may or not be necessary 
    // Im not sure if you can have a device thats not currentDevice can you?
    // if ([self isEqual:[UIDevice currentDevice]]) {

    NSString* platform =  [[self.systemName copy] autorelease];
    return platform;

    // Could probably shorten to just
    // return [[self.systemName copy] autorelease];

    // or - return [NSString stringWithString:self.systemName];
}

这里是utsname machine的obj-c版本(代码如下:NSString* platform =  [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];)。utsname包含以下成员:

char sysname[]   操作系统实现的名称
char nodename[] 在实现相关通信网络中此节点的名称
char release[]   此实现的当前发布级别
char version[]   此发布的当前版本级别
char machine[]   运行该系统的硬件类型名称

UIDevice类参考文档中,systemName返回设备上运行的操作系统名称(只读):@property (nonatomic, readonly, retain) NSString *system
但是,由于systemName仅返回@"iPhone OS",要获取实际设备型号,必须使用c代码。以下是另一种方法:
#include <sys/types.h>
#include <sys/sysctl.h>

- (NSString *)machine {
     size_t size;

    // Set 'oldp' parameter to NULL to get the size of the data
    // returned so we can allocate appropriate amount of space
    sysctlbyname("hw.machine", NULL, &size, NULL, 0); 

    // Allocate the space to store name
    char *name = malloc(size);

    // Get the platform name
    sysctlbyname("hw.machine", name, &size, NULL, 0);

    // Place name into a string
    NSString *machine = [NSString stringWithCString:name];

    // Done with this
    free(name);

    return machine;
}

是的,这是Objective-C语言,但它并不能区分设备... - Oliver
我以为你在问如何将 platformCode 方法的 C 代码转换为 Objective-C?你还有其他问题吗? - chown
不,那正是我所要求的,但你的代码返回的值与C调用不同,真的很差。事实上,据我所见,它也没有返回任何可用于实现与C调用相同目标的东西。 - Oliver
啊,我想我明白你的问题了。但是答案是你必须使用 C 语言。没有 ObjC 的方法可以获取型号。 - chown
UIDevice类参考的更新链接:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/ - Spencer Williams

1

您需要使用低级别的C调用来获取infoString。为了我的目的,我编写了一个小型的Objective-C库,将其抽象化并呈现出Objective-C接口。

NSLog(@"Big model number: %d", deviceDetails.bigModel);
//Big model number: 4

NSLog(@"Small model number: %d", deviceDetails.smallModel);
//Small model number: 1

if (deviceDetails.model == GBDeviceModeliPhone4S) {
    NSLog(@"It's a 4S");
}
//It's a 4S

if (deviceDetails.family != GBDeviceFamilyiPad) {
    NSLog(@"It's not an iPad");
}
//It's not an iPad

NSLog(@"systemInfo string: %@", [GBDeviceInfo rawSystemInfoString]);
//systemInfo string: iPhone4,1

如果您喜欢,可以在 Github 上获取它:GBDeviceInfo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接