New file |
| | |
| | | // |
| | | // UIDevice+YYAdd.m |
| | | // YYCategories <https://github.com/ibireme/YYCategories> |
| | | // |
| | | // Created by ibireme on 13/4/3. |
| | | // Copyright (c) 2015 ibireme. |
| | | // |
| | | // This source code is licensed under the MIT-style license found in the |
| | | // LICENSE file in the root directory of this source tree. |
| | | // |
| | | |
| | | #import "UIDevice+YYAdd.h" |
| | | #include <sys/socket.h> |
| | | #include <sys/sysctl.h> |
| | | #include <net/if.h> |
| | | #include <net/if_dl.h> |
| | | #include <mach/mach.h> |
| | | #include <arpa/inet.h> |
| | | #include <ifaddrs.h> |
| | | #import "YYCategoriesMacro.h" |
| | | #import "NSString+YYAdd.h" |
| | | |
| | | YYSYNTH_DUMMY_CLASS(UIDevice_YYAdd) |
| | | |
| | | |
| | | @implementation UIDevice (YYAdd) |
| | | |
| | | + (double)systemVersion { |
| | | static double version; |
| | | static dispatch_once_t onceToken; |
| | | dispatch_once(&onceToken, ^{ |
| | | version = [UIDevice currentDevice].systemVersion.doubleValue; |
| | | }); |
| | | return version; |
| | | } |
| | | |
| | | - (BOOL)isPad { |
| | | static dispatch_once_t one; |
| | | static BOOL pad; |
| | | dispatch_once(&one, ^{ |
| | | pad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad; |
| | | }); |
| | | return pad; |
| | | } |
| | | |
| | | - (BOOL)isSimulator { |
| | | static dispatch_once_t one; |
| | | static BOOL simu; |
| | | dispatch_once(&one, ^{ |
| | | simu = NSNotFound != [[self model] rangeOfString:@"Simulator"].location; |
| | | }); |
| | | return simu; |
| | | } |
| | | |
| | | - (BOOL)isJailbroken { |
| | | if ([self isSimulator]) return NO; // Dont't check simulator |
| | | |
| | | // iOS9 URL Scheme query changed ... |
| | | // NSURL *cydiaURL = [NSURL URLWithString:@"cydia://package"]; |
| | | // if ([[UIApplication sharedApplication] canOpenURL:cydiaURL]) return YES; |
| | | |
| | | NSArray *paths = @[@"/Applications/Cydia.app", |
| | | @"/private/var/lib/apt/", |
| | | @"/private/var/lib/cydia", |
| | | @"/private/var/stash"]; |
| | | for (NSString *path in paths) { |
| | | if ([[NSFileManager defaultManager] fileExistsAtPath:path]) return YES; |
| | | } |
| | | |
| | | FILE *bash = fopen("/bin/bash", "r"); |
| | | if (bash != NULL) { |
| | | fclose(bash); |
| | | return YES; |
| | | } |
| | | |
| | | NSString *path = [NSString stringWithFormat:@"/private/%@", [NSString stringWithUUID]]; |
| | | if ([@"test" writeToFile : path atomically : YES encoding : NSUTF8StringEncoding error : NULL]) { |
| | | [[NSFileManager defaultManager] removeItemAtPath:path error:nil]; |
| | | return YES; |
| | | } |
| | | |
| | | return NO; |
| | | } |
| | | |
| | | #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED |
| | | - (BOOL)canMakePhoneCalls { |
| | | __block BOOL can; |
| | | static dispatch_once_t onceToken; |
| | | dispatch_once(&onceToken, ^{ |
| | | can = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]]; |
| | | }); |
| | | return can; |
| | | } |
| | | #endif |
| | | |
| | | - (NSString *)ipAddressWithIfaName:(NSString *)name { |
| | | if (name.length == 0) return nil; |
| | | NSString *address = nil; |
| | | struct ifaddrs *addrs = NULL; |
| | | if (getifaddrs(&addrs) == 0) { |
| | | struct ifaddrs *addr = addrs; |
| | | while (addr) { |
| | | if ([[NSString stringWithUTF8String:addr->ifa_name] isEqualToString:name]) { |
| | | sa_family_t family = addr->ifa_addr->sa_family; |
| | | switch (family) { |
| | | case AF_INET: { // IPv4 |
| | | char str[INET_ADDRSTRLEN] = {0}; |
| | | inet_ntop(family, &(((struct sockaddr_in *)addr->ifa_addr)->sin_addr), str, sizeof(str)); |
| | | if (strlen(str) > 0) { |
| | | address = [NSString stringWithUTF8String:str]; |
| | | } |
| | | } break; |
| | | |
| | | case AF_INET6: { // IPv6 |
| | | char str[INET6_ADDRSTRLEN] = {0}; |
| | | inet_ntop(family, &(((struct sockaddr_in6 *)addr->ifa_addr)->sin6_addr), str, sizeof(str)); |
| | | if (strlen(str) > 0) { |
| | | address = [NSString stringWithUTF8String:str]; |
| | | } |
| | | } |
| | | |
| | | default: break; |
| | | } |
| | | if (address) break; |
| | | } |
| | | addr = addr->ifa_next; |
| | | } |
| | | } |
| | | freeifaddrs(addrs); |
| | | return address; |
| | | } |
| | | |
| | | - (NSString *)ipAddressWIFI { |
| | | return [self ipAddressWithIfaName:@"en0"]; |
| | | } |
| | | |
| | | - (NSString *)ipAddressCell { |
| | | return [self ipAddressWithIfaName:@"pdp_ip0"]; |
| | | } |
| | | |
| | | |
| | | typedef struct { |
| | | uint64_t en_in; |
| | | uint64_t en_out; |
| | | uint64_t pdp_ip_in; |
| | | uint64_t pdp_ip_out; |
| | | uint64_t awdl_in; |
| | | uint64_t awdl_out; |
| | | } yy_net_interface_counter; |
| | | |
| | | |
| | | static uint64_t yy_net_counter_add(uint64_t counter, uint64_t bytes) { |
| | | if (bytes < (counter % 0xFFFFFFFF)) { |
| | | counter += 0xFFFFFFFF - (counter % 0xFFFFFFFF); |
| | | counter += bytes; |
| | | } else { |
| | | counter = bytes; |
| | | } |
| | | return counter; |
| | | } |
| | | |
| | | static uint64_t yy_net_counter_get_by_type(yy_net_interface_counter *counter, YYNetworkTrafficType type) { |
| | | uint64_t bytes = 0; |
| | | if (type & YYNetworkTrafficTypeWWANSent) bytes += counter->pdp_ip_out; |
| | | if (type & YYNetworkTrafficTypeWWANReceived) bytes += counter->pdp_ip_in; |
| | | if (type & YYNetworkTrafficTypeWIFISent) bytes += counter->en_out; |
| | | if (type & YYNetworkTrafficTypeWIFIReceived) bytes += counter->en_in; |
| | | if (type & YYNetworkTrafficTypeAWDLSent) bytes += counter->awdl_out; |
| | | if (type & YYNetworkTrafficTypeAWDLReceived) bytes += counter->awdl_in; |
| | | return bytes; |
| | | } |
| | | |
| | | static yy_net_interface_counter yy_get_net_interface_counter() { |
| | | static dispatch_semaphore_t lock; |
| | | static NSMutableDictionary *sharedInCounters; |
| | | static NSMutableDictionary *sharedOutCounters; |
| | | static dispatch_once_t onceToken; |
| | | dispatch_once(&onceToken, ^{ |
| | | sharedInCounters = [NSMutableDictionary new]; |
| | | sharedOutCounters = [NSMutableDictionary new]; |
| | | lock = dispatch_semaphore_create(1); |
| | | }); |
| | | |
| | | yy_net_interface_counter counter = {0}; |
| | | struct ifaddrs *addrs; |
| | | const struct ifaddrs *cursor; |
| | | if (getifaddrs(&addrs) == 0) { |
| | | cursor = addrs; |
| | | dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); |
| | | while (cursor) { |
| | | if (cursor->ifa_addr->sa_family == AF_LINK) { |
| | | const struct if_data *data = cursor->ifa_data; |
| | | NSString *name = cursor->ifa_name ? [NSString stringWithUTF8String:cursor->ifa_name] : nil; |
| | | if (name) { |
| | | uint64_t counter_in = ((NSNumber *)sharedInCounters[name]).unsignedLongLongValue; |
| | | counter_in = yy_net_counter_add(counter_in, data->ifi_ibytes); |
| | | sharedInCounters[name] = @(counter_in); |
| | | |
| | | uint64_t counter_out = ((NSNumber *)sharedOutCounters[name]).unsignedLongLongValue; |
| | | counter_out = yy_net_counter_add(counter_out, data->ifi_obytes); |
| | | sharedOutCounters[name] = @(counter_out); |
| | | |
| | | if ([name hasPrefix:@"en"]) { |
| | | counter.en_in += counter_in; |
| | | counter.en_out += counter_out; |
| | | } else if ([name hasPrefix:@"awdl"]) { |
| | | counter.awdl_in += counter_in; |
| | | counter.awdl_out += counter_out; |
| | | } else if ([name hasPrefix:@"pdp_ip"]) { |
| | | counter.pdp_ip_in += counter_in; |
| | | counter.pdp_ip_out += counter_out; |
| | | } |
| | | } |
| | | } |
| | | cursor = cursor->ifa_next; |
| | | } |
| | | dispatch_semaphore_signal(lock); |
| | | freeifaddrs(addrs); |
| | | } |
| | | |
| | | return counter; |
| | | } |
| | | |
| | | - (uint64_t)getNetworkTrafficBytes:(YYNetworkTrafficType)types { |
| | | yy_net_interface_counter counter = yy_get_net_interface_counter(); |
| | | return yy_net_counter_get_by_type(&counter, types); |
| | | } |
| | | |
| | | - (NSString *)machineModel { |
| | | static dispatch_once_t one; |
| | | static NSString *model; |
| | | dispatch_once(&one, ^{ |
| | | size_t size; |
| | | sysctlbyname("hw.machine", NULL, &size, NULL, 0); |
| | | char *machine = malloc(size); |
| | | sysctlbyname("hw.machine", machine, &size, NULL, 0); |
| | | model = [NSString stringWithUTF8String:machine]; |
| | | free(machine); |
| | | }); |
| | | return model; |
| | | } |
| | | |
| | | - (NSString *)machineModelName { |
| | | static dispatch_once_t one; |
| | | static NSString *name; |
| | | dispatch_once(&one, ^{ |
| | | NSString *model = [self machineModel]; |
| | | if (!model) return; |
| | | NSDictionary *dic = @{ |
| | | @"Watch1,1" : @"Apple Watch 38mm", |
| | | @"Watch1,2" : @"Apple Watch 42mm", |
| | | @"Watch2,3" : @"Apple Watch Series 2 38mm", |
| | | @"Watch2,4" : @"Apple Watch Series 2 42mm", |
| | | @"Watch2,6" : @"Apple Watch Series 1 38mm", |
| | | @"Watch1,7" : @"Apple Watch Series 1 42mm", |
| | | |
| | | @"iPod1,1" : @"iPod touch 1", |
| | | @"iPod2,1" : @"iPod touch 2", |
| | | @"iPod3,1" : @"iPod touch 3", |
| | | @"iPod4,1" : @"iPod touch 4", |
| | | @"iPod5,1" : @"iPod touch 5", |
| | | @"iPod7,1" : @"iPod touch 6", |
| | | |
| | | @"iPhone1,1" : @"iPhone 1G", |
| | | @"iPhone1,2" : @"iPhone 3G", |
| | | @"iPhone2,1" : @"iPhone 3GS", |
| | | @"iPhone3,1" : @"iPhone 4 (GSM)", |
| | | @"iPhone3,2" : @"iPhone 4", |
| | | @"iPhone3,3" : @"iPhone 4 (CDMA)", |
| | | @"iPhone4,1" : @"iPhone 4S", |
| | | @"iPhone5,1" : @"iPhone 5", |
| | | @"iPhone5,2" : @"iPhone 5", |
| | | @"iPhone5,3" : @"iPhone 5c", |
| | | @"iPhone5,4" : @"iPhone 5c", |
| | | @"iPhone6,1" : @"iPhone 5s", |
| | | @"iPhone6,2" : @"iPhone 5s", |
| | | @"iPhone7,1" : @"iPhone 6 Plus", |
| | | @"iPhone7,2" : @"iPhone 6", |
| | | @"iPhone8,1" : @"iPhone 6s", |
| | | @"iPhone8,2" : @"iPhone 6s Plus", |
| | | @"iPhone8,4" : @"iPhone SE", |
| | | @"iPhone9,1" : @"iPhone 7", |
| | | @"iPhone9,2" : @"iPhone 7 Plus", |
| | | @"iPhone9,3" : @"iPhone 7", |
| | | @"iPhone9,4" : @"iPhone 7 Plus", |
| | | |
| | | @"iPad1,1" : @"iPad 1", |
| | | @"iPad2,1" : @"iPad 2 (WiFi)", |
| | | @"iPad2,2" : @"iPad 2 (GSM)", |
| | | @"iPad2,3" : @"iPad 2 (CDMA)", |
| | | @"iPad2,4" : @"iPad 2", |
| | | @"iPad2,5" : @"iPad mini 1", |
| | | @"iPad2,6" : @"iPad mini 1", |
| | | @"iPad2,7" : @"iPad mini 1", |
| | | @"iPad3,1" : @"iPad 3 (WiFi)", |
| | | @"iPad3,2" : @"iPad 3 (4G)", |
| | | @"iPad3,3" : @"iPad 3 (4G)", |
| | | @"iPad3,4" : @"iPad 4", |
| | | @"iPad3,5" : @"iPad 4", |
| | | @"iPad3,6" : @"iPad 4", |
| | | @"iPad4,1" : @"iPad Air", |
| | | @"iPad4,2" : @"iPad Air", |
| | | @"iPad4,3" : @"iPad Air", |
| | | @"iPad4,4" : @"iPad mini 2", |
| | | @"iPad4,5" : @"iPad mini 2", |
| | | @"iPad4,6" : @"iPad mini 2", |
| | | @"iPad4,7" : @"iPad mini 3", |
| | | @"iPad4,8" : @"iPad mini 3", |
| | | @"iPad4,9" : @"iPad mini 3", |
| | | @"iPad5,1" : @"iPad mini 4", |
| | | @"iPad5,2" : @"iPad mini 4", |
| | | @"iPad5,3" : @"iPad Air 2", |
| | | @"iPad5,4" : @"iPad Air 2", |
| | | @"iPad6,3" : @"iPad Pro (9.7 inch)", |
| | | @"iPad6,4" : @"iPad Pro (9.7 inch)", |
| | | @"iPad6,7" : @"iPad Pro (12.9 inch)", |
| | | @"iPad6,8" : @"iPad Pro (12.9 inch)", |
| | | |
| | | @"AppleTV2,1" : @"Apple TV 2", |
| | | @"AppleTV3,1" : @"Apple TV 3", |
| | | @"AppleTV3,2" : @"Apple TV 3", |
| | | @"AppleTV5,3" : @"Apple TV 4", |
| | | |
| | | @"i386" : @"Simulator x86", |
| | | @"x86_64" : @"Simulator x64", |
| | | }; |
| | | name = dic[model]; |
| | | if (!name) name = model; |
| | | }); |
| | | return name; |
| | | } |
| | | |
| | | - (NSDate *)systemUptime { |
| | | NSTimeInterval time = [[NSProcessInfo processInfo] systemUptime]; |
| | | return [[NSDate alloc] initWithTimeIntervalSinceNow:(0 - time)]; |
| | | } |
| | | |
| | | - (int64_t)diskSpace { |
| | | 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)diskSpaceFree { |
| | | 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)diskSpaceUsed { |
| | | int64_t total = self.diskSpace; |
| | | int64_t free = self.diskSpaceFree; |
| | | if (total < 0 || free < 0) return -1; |
| | | int64_t used = total - free; |
| | | if (used < 0) used = -1; |
| | | return used; |
| | | } |
| | | |
| | | - (int64_t)memoryTotal { |
| | | int64_t mem = [[NSProcessInfo processInfo] physicalMemory]; |
| | | if (mem < -1) mem = -1; |
| | | return mem; |
| | | } |
| | | |
| | | - (int64_t)memoryUsed { |
| | | mach_port_t host_port = mach_host_self(); |
| | | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
| | | vm_size_t page_size; |
| | | vm_statistics_data_t vm_stat; |
| | | kern_return_t kern; |
| | | |
| | | kern = host_page_size(host_port, &page_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | return page_size * (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count); |
| | | } |
| | | |
| | | - (int64_t)memoryFree { |
| | | mach_port_t host_port = mach_host_self(); |
| | | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
| | | vm_size_t page_size; |
| | | vm_statistics_data_t vm_stat; |
| | | kern_return_t kern; |
| | | |
| | | kern = host_page_size(host_port, &page_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | return vm_stat.free_count * page_size; |
| | | } |
| | | |
| | | - (int64_t)memoryActive { |
| | | mach_port_t host_port = mach_host_self(); |
| | | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
| | | vm_size_t page_size; |
| | | vm_statistics_data_t vm_stat; |
| | | kern_return_t kern; |
| | | |
| | | kern = host_page_size(host_port, &page_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | return vm_stat.active_count * page_size; |
| | | } |
| | | |
| | | - (int64_t)memoryInactive { |
| | | mach_port_t host_port = mach_host_self(); |
| | | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
| | | vm_size_t page_size; |
| | | vm_statistics_data_t vm_stat; |
| | | kern_return_t kern; |
| | | |
| | | kern = host_page_size(host_port, &page_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | return vm_stat.inactive_count * page_size; |
| | | } |
| | | |
| | | - (int64_t)memoryWired { |
| | | mach_port_t host_port = mach_host_self(); |
| | | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
| | | vm_size_t page_size; |
| | | vm_statistics_data_t vm_stat; |
| | | kern_return_t kern; |
| | | |
| | | kern = host_page_size(host_port, &page_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | return vm_stat.wire_count * page_size; |
| | | } |
| | | |
| | | - (int64_t)memoryPurgable { |
| | | mach_port_t host_port = mach_host_self(); |
| | | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); |
| | | vm_size_t page_size; |
| | | vm_statistics_data_t vm_stat; |
| | | kern_return_t kern; |
| | | |
| | | kern = host_page_size(host_port, &page_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); |
| | | if (kern != KERN_SUCCESS) return -1; |
| | | return vm_stat.purgeable_count * page_size; |
| | | } |
| | | |
| | | - (NSUInteger)cpuCount { |
| | | return [NSProcessInfo processInfo].activeProcessorCount; |
| | | } |
| | | |
| | | - (float)cpuUsage { |
| | | float cpu = 0; |
| | | NSArray *cpus = [self cpuUsagePerProcessor]; |
| | | if (cpus.count == 0) return -1; |
| | | for (NSNumber *n in cpus) { |
| | | cpu += n.floatValue; |
| | | } |
| | | return cpu; |
| | | } |
| | | |
| | | - (NSArray *)cpuUsagePerProcessor { |
| | | processor_info_array_t _cpuInfo, _prevCPUInfo = nil; |
| | | mach_msg_type_number_t _numCPUInfo, _numPrevCPUInfo = 0; |
| | | unsigned _numCPUs; |
| | | NSLock *_cpuUsageLock; |
| | | |
| | | int _mib[2U] = { CTL_HW, HW_NCPU }; |
| | | size_t _sizeOfNumCPUs = sizeof(_numCPUs); |
| | | int _status = sysctl(_mib, 2U, &_numCPUs, &_sizeOfNumCPUs, NULL, 0U); |
| | | if (_status) |
| | | _numCPUs = 1; |
| | | |
| | | _cpuUsageLock = [[NSLock alloc] init]; |
| | | |
| | | natural_t _numCPUsU = 0U; |
| | | kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &_numCPUsU, &_cpuInfo, &_numCPUInfo); |
| | | if (err == KERN_SUCCESS) { |
| | | [_cpuUsageLock lock]; |
| | | |
| | | NSMutableArray *cpus = [NSMutableArray new]; |
| | | for (unsigned i = 0U; i < _numCPUs; ++i) { |
| | | Float32 _inUse, _total; |
| | | if (_prevCPUInfo) { |
| | | _inUse = ( |
| | | (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER]) |
| | | + (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM]) |
| | | + (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE]) |
| | | ); |
| | | _total = _inUse + (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]); |
| | | } else { |
| | | _inUse = _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] + _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] + _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE]; |
| | | _total = _inUse + _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]; |
| | | } |
| | | [cpus addObject:@(_inUse / _total)]; |
| | | } |
| | | |
| | | [_cpuUsageLock unlock]; |
| | | if (_prevCPUInfo) { |
| | | size_t prevCpuInfoSize = sizeof(integer_t) * _numPrevCPUInfo; |
| | | vm_deallocate(mach_task_self(), (vm_address_t)_prevCPUInfo, prevCpuInfoSize); |
| | | } |
| | | return cpus; |
| | | } else { |
| | | return nil; |
| | | } |
| | | } |
| | | |
| | | @end |