Определите устройство пользователя с помощью iOS SDK и полного кода Cocoa Touch / Objective-C

#iphone #ios #ipad #sdk #ipod

#iPhone #iOS #iPad #sdk #ipod

Вопрос:

Я написал следующую категорию пользовательских устройств на основе разных источников. Я обновил 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(amp;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
  

Комментарии:

1. Это совершенно допустимый Objective-C (как и весь код C), он также не слишком низкоуровневый (я рекомендую использовать перечисления, а не строки для конечных наборов с несколькими вариантами выбора).

Ответ №1:

Это можно считать способом «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];
}
  

Это будет версия obj-c utsname machine (из этой строки: NSString* platform =  [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; ).

utsname :

<sys/utsname.h> Заголовок определяет структуру 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, amp;size, NULL, 0); 

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

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

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

    // Done with this
    free(name);

    return machine;
}
  

Комментарии:

1. Да, это objective-C, но это не позволяет различать устройства…

2. Я думал, вы спрашивали, как преобразовать код c для platformCode метода в objective-c? Было ли что-то еще, о чем вы спрашивали?

3. Нет, это было именно то, о чем я просил, но ваш код не возвращает те же значения, что и вызов C, он действительно менее плохой. На самом деле, насколько я видел, он не возвращает ничего, что можно было бы использовать для достижения той же цели, что и вызов C.

4. Ах, я думаю, я понимаю, о чем вы спрашиваете. Но ответ на это заключается в том, что вы должны использовать c. Нет способа ObjC получить номер модели.

5. Обновлена ссылка для ссылки на класс UIDevice: developer.apple.com/library/ios/documentation/UIKit/Reference /…

Ответ №2:

Вам придется использовать вызов C низкого уровня, чтобы получить информацию. Для своих целей я написал крошечную библиотеку 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