APP在开发的过程中,有时候为了bug的跟踪,需要收集用户使用手机的设备,手机系统版本,手机型号,以及应用版本,应用信息等等。这些的信息便于开发者诊断问题,是能够通过开发api可以获取到的,iOS的SDK中提供了三种方式来获取APP的信息,他们分别是UIDevice,NSBundle,NSLocale.
一、UIDevice 帮助我们全方位的了解所使用的设备的信息
//手机名称
NSString *userPhoneNameStr = [[UIDevice currentDevice] name];
//手机系统名称
NSString *deviceNameStr = [[UIDevice currentDevice] systemName];
//手机系统版本号
NSString *systemVersionStr = [[UIDevice currentDevice] systemVersion];
//类型 是模拟器还是真机
NSString *phoneModelStr = [[UIDevice currentDevice] model];
//电池电量
CGFloat batteryLevel = [[UIDevice currentDevice] batteryLevel];
//地方型号 (国际化区域名称)
NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel];
二、NSBundle ,这是一个目录,我们称之为程序的main bundle,通过这个目录获取应用的信息,比如说应用的名称,版本号,应用软件的版本
这里总共有29个,我在这里挑选了几个比较常用的
//app 应用信息的获取字典类型,
NSDictionary * dicInfo =[[NSBundle mainBundle] infoDictionary];
//当前应用名称
NSString * appNameStr =[dicInfo objectForKey:@"CFBundleName"];
//当前应用版本号
NSString * appVersionStr =[dicInfo objectForKey:@"CFBundleShortVersionString"];
//当前应用构建版本号(build号)
NSString * appBuildStr =[dicInfo objectForKey:@"CFBundleVersion"];
//获取build号另一种方式
NSString *version = [[[NSBundle mainBundle]infoDictionary]objectForKey:(NSString *)kCFBundleVersionKey];
//Xcode 版本号
NSString * appXcodeStr =[dicInfo objectForKey:@"DTXcode"];
//模拟器系统版本号
NSString * appSDKNameStr = [dicInfo objectForKey:@"DTSDKName"];
三、NSLocale 可以获取用户的本地化信息的设置,比如说:国家,语言,日期的格式。
四、磁盘空间
// 获取磁盘总空间
- (int64_t)getTotalDiskSpace {
NSError *error = nil;
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
if (error) return -1;
int64_t space = [[attrs objectForKey:NSFileSystemSize] longLongValue];
if (space < 0) space = -1;
return space;
}
// 获取未使用的磁盘空间
- (int64_t)getFreeDiskSpace {
NSError *error = nil;
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
if (error) return -1;
int64_t space = [[attrs objectForKey:NSFileSystemFreeSize] longLongValue];
if (space < 0) space = -1;
return space;
}
// 获取已使用的磁盘空间
- (int64_t)getUsedDiskSpace {
int64_t totalDisk = [self getTotalDiskSpace];
int64_t freeDisk = [self getFreeDiskSpace];
if (totalDisk < 0 || freeDisk < 0) return -1;
int64_t usedDisk = totalDisk - freeDisk;
if (usedDisk < 0) usedDisk = -1;
return usedDisk;
}
五、运营商
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [info subscriberCellularProvider];
//当前手机所属运营商名称
NSString *mobileCarrier;
//先判断有没有SIM卡,如果没有则不获取本机运营商
if (!carrier.isoCountryCode) {
mobileCarrier = @"无运营商";
}else{
mobileCarrier = [carrier carrierName];
}
六、获取设备型号
- (NSString *)iphoneType {
//需要导入头文件:#import <sys/utsname.h>
struct utsname systemInfo;
uname(&systemInfo);
NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 2G";
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 @"iPhone 4";
if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4";
if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5";
if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c";
if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c";
if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s";
if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s";
if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";
if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s";
if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus";
if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE";
if ([platform isEqualToString:@"iPhone9,1"]) return @"iPhone 7";
if ([platform isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus";
return platform;
}
七、地理位置
使用CLLocationManager和CLLocation两个类
-(void)Collocaction{
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager requestAlwaysAuthorization];//请求授权
if ([CLLocationManager locationServicesEnabled]) {
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
self.locationManager.distanceFilter = 200.0f;
[self.locationManager startUpdatingLocation];
}
else {
NSLog(@"请开启定位功能!");
}
}
//定位代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
// 获取当前所在的城市名
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
//根据经纬度反向地理编译出地址信息
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error)
{
if (array.count > 0)
{
CLPlacemark *placemark = [array objectAtIndex:0];
//获取城市
NSString *city = placemark.locality;
if (!city) {
//四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
city = placemark.administrativeArea;
}
//详细地址
NSString *location = placemark.name;
//拼接成最终的位置
NSString *myLocation = [NSString stringWithFormat:@"%@%@",city,location];
}
else if (error == nil && [array count] == 0)
{
NSLog(@"No results were returned.");
}
else if (error != nil)
{
NSLog(@"An error occurred = %@", error);
}
}];
//停止定位
[manager stopUpdatingLocation];
}
// 定位失误时调用
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"error:%@",error);
}
八、获取设备的IP地址
//获取IP地址
#import <ifaddrs.h>
#import <arpa/inet.h>
#include <net/if.h>
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
//#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
//第一种适合在WiFi情况下使用,但是如果切换到蜂窝数据下,则返回数据@“error”
//获取设备当前网络IP地址
- (NSString *)getIPAddress:(BOOL)preferIPv4{
NSArray *searchArray = preferIPv4 ?
@[ /*IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6,*/ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :
@[ /*IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4,*/ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;
NSDictionary *addresses = [self getIPAddresses];
NSLog(@"addresses: %@", addresses);
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if(address) *stop = YES;
} ];
return address ? address : @"0.0.0.0";
}
//第二种可以获取蜂窝数据下的IP地址
//获取所有相关IP信息
- (NSDictionary *)getIPAddresses{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces)) {
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next) {
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
continue; // deeply nested code harder to read
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
NSString *type;
if(addr->sin_family == AF_INET) {
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if(type) {
NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
// Free memory
freeifaddrs(interfaces);
}
return [addresses count] ? addresses : nil;
}
// Get IP Address
- (NSString *)getIPAddress {
NSString *address = @"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
}
九、获取设备的位置
#import <CoreLocation/CoreLocation.h>
遵守CLLocationManagerDelegate代理
在info.plist中加入:
//允许在前台使用时获取GPS的描述
定位权限:Privacy - Location When In Use Usage Description
//允许永久使用GPS描述
定位权限: Privacy - Location Always Usage Description
在Build Phases 添加CoreLocation.framework库
{
CLLocationManager *locationmanager;//定位服务
NSString *currentCity;//当前城市
NSString *strlatitude;//经度
NSString *strlongitude;//纬度
}
//获取经纬度
[self getLocation];
-(void)getLocation
{
//判断定位功能是否打开
if ([CLLocationManager locationServicesEnabled]) {
locationmanager = [[CLLocationManager alloc]init];
locationmanager.delegate = self;
[locationmanager requestAlwaysAuthorization];
currentCity = [NSString new];
[locationmanager requestWhenInUseAuthorization];
//设置寻址精度
locationmanager.desiredAccuracy = kCLLocationAccuracyBest;
locationmanager.distanceFilter = 5.0;
[locationmanager startUpdatingLocation];
}
}
#pragma mark CoreLocation delegate (定位失败)
//定位失败后调用此代理方法
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
//设置提示提醒用户打开定位服务
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"允许定位提示" message:@"请在设置中打开定位" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"打开定位" style:UIAlertActionStyleDefault handler:nil];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:okAction];
[alert addAction:cancelAction];
[self presentViewController:alert animated:YES completion:nil];
}
#pragma mark 定位成功后则执行此代理方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
[locationmanager stopUpdatingHeading];
//旧址
CLLocation *currentLocation = [locations lastObject];
CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
//打印当前的经度与纬度
NSLog(@"%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude);
//反地理编码
[geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
if (placemarks.count > 0) {
CLPlacemark *placeMark = placemarks[0];
currentCity = placeMark.locality;
if (!currentCity) {
currentCity = @"无法定位当前城市";
}
/*看需求定义一个全局变量来接收赋值*/
NSLog(@"----%@",placeMark.country);//当前国家
NSLog(@"%@",currentCity);//当前的城市
// NSLog(@"%@",placeMark.subLocality);//当前的位置
// NSLog(@"%@",placeMark.thoroughfare);//当前街道
// NSLog(@"%@",placeMark.name);//具体地址
}
}];
}