I am having a memory leak in the code below but don't really know how to fix it. I tried making machine = nil; but that didn't work. Anyone have any suggestions? Thanks in advance.
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
if ([platform isEqualToString:#"iPhone3,1"] || [platform isEqualToString:#"iPhone3,2"] || [platform isEqualToString:#"iPhone3,3"] || [platform isEqualToString:#"iPhone4,1"])
[UINavigationBar appearance].barTintColor = [UIColor colorWithRed:255.0/255.0 green:220.0/255.0 blue:0.0/255.0 alpha:0.9];
machine = nil;
I get the leak in stringWithCSString:machine: potential leak of memory pointed to by 'machine'.
Calls to malloc need to be paired with calls to free.
Change machine = nil to free(machine).
BTW - your code be made a lot easier:
#include <sys/utsname.h>
struct utsname si;
uname(&si);
if (strcmp(si.machine, "iPhone3,1") == 0 || strcmp(si.machine, "iPhone3,2") == 0 || strcmp(si.machine, "iPhone3,3") == 0 || strcmp(si.machine, "iPhone4,1") == 0) {
}
No need for the memory management or creating NSString objects.
Related
Is there a way to programmatically detect iOS version's build number,
For example iOS version 9.0.2(13A452).
I know how to detect iOS version eg: 9.0.2.
Is there any API to detect 13A452?
Thanks in advance.
Figured I'd put the code up incase anyone needs it (works at run time), since it's slightly tricky to process!
MAKE SURE YOU #include <sys/sysctl.h>
//make sure you `#include <sys/sysctl.h>`
NSString *ctlKey = #"kern.osversion";
BOOL buildValueFound;
NSString *buildValue;
size_t size = 0;
if (sysctlbyname([ctlKey UTF8String], NULL, &size, NULL, 0) == -1) {
buildValueFound = NO;
} else {
char *machine = calloc( 1, size );
sysctlbyname([ctlKey UTF8String], machine, &size, NULL, 0);
NSString *ctlValue = [NSString stringWithCString:machine encoding:[NSString defaultCStringEncoding]];
free(machine);
buildValue = ctlValue;
buildValueFound = YES;
}
if (buildValueFound) {
NSLog(#"%#", buildValue);
} else {
NSLog(#"No build value found");
}
I have figured this out. Using KERN_OSVERSION on function sysctl returns iOS build number.
I have read the answer to this question, Identify new iPhone model on xcode (5, 5c, 5s) and would like to add this as an NSString to my MFMailCompose. I have tried using this method but am not having any luck. Someone please help me.
Sorry I am new to Xcode.
NSString *iOS = [[UIDevice currentDevice] systemVersion];
NSString *model = [[UIDevice currentDevice] model];
NSString *appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
NSString *name = [[UIDevice currentDevice] name];
NSString *appID=#" ";
NSString *appStoreURL =[NSString stringWithFormat:#"https://itunes.apple.com/us/app/scanmarks/id926114469?ls=1&mt=8", appID];
NSString *body = [NSString stringWithFormat:#"I need help with\n\n\n----------\n Name: %#\nDevice: %# (%#)\n Scanmarks Version: %#\n",name,model,iOS,appVersionString];
It currently shows:
I would like it to show the iPhone Device model like Tweetbot does
I have added the suggested and now have this:
Using the link you you put in your question, if you just want it to say the iPhone platform you would just use this portion of their answer :
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);
That will translate to iPhone7,2 etc. just pass the NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; string 'platform' into your message body
If you want to convert that to whatever string you want that's when the other portion comes into play. This is the only time you'll use the other part and all of the conversions in their answer:
NSString *convertPlatformToString = [self platformType:platform]);
Example for putting in mail message:
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);
NSString *body = [NSString stringWithFormat:#"Platform is %#", platform];
Harvey,
I built an open source tool that does exactly what you want. Feel free to use it or browse through the code to see how I accomplished what you're asking.
https://github.com/michaelpatzer/MPFeedbackMailComposeViewController
Is there a way that I can know how long the apps in the foreground has been running? I have three possible solutions in mind:
I. use battery consumption and battery consumption rate (iOS 8 and later tell you the battery usage of the app, but the batter consumption will be difficult to handle)
II. use system processes monitor
III. use Apple's diagnostics logs. This approach is quite "backdoor." Plus I am not sure if Apple allows us to use the information or not.
Can someone tell me if any of the above solution is realistic? If not, I want to know is it possible to find out the duration of a running app on iOS at all?
You can't access any data like that from other apps. Because every app works in its own sandbox and so you don't have the possibility to do that. You can't know because of the battery it consumes, how long an app is running. It depends on the frameworks it uses etc. Also if it's a game with high resolution graphics etc.
So: None of your ideas are possible.
With sysctl, you can get many informations about running processes. See in this code, you can find all running processes and also the started time of each process. This code is not private API so it should be accepted by Apple in case of posting it in Apple Store. Take a look in 'struct kinfo_proc' in sysctl.h, you will find useful infos. I don't know how to detect if a process is in foreground or background. I can find just the start_time, then to calculate running time. However, as you run this application in foreground, other processes are likely in background, isn't it?
#import <sys/sysctl.h>
- (NSArray *)runningProcesses
{
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc *process = NULL;
struct kinfo_proc *newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess) {
if (process) {
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0) {
if (size % sizeof(struct kinfo_proc) == 0) {
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess) {
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--) {
NSString *processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString *processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
struct timeval t = process[i].kp_proc.p_un.__p_starttime;
long ms = t.tv_sec;
NSDate *startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:ms];
NSDictionary *dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName, startDate, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName",#"StartDate", nil]];
[array addObject:dict];
}
free(process);
return array;
}
}
}
return nil;
}
I am a new developer in iOS Developing. I faced a problem on current device. According to requirement i have to design app for all device. So anybody can help me how to get Current device & current platform of iOS?
For current device i am using this code:
NSString *deviceType = [[UIDevice currentDevice] model];
My requirement is i have to adjust UITableView row height according to device.
I think you got my question. If you need any information please tell me.
Thanks in advanced.
Ok try this one.
NSString *deviceType = [[UIDevice currentDevice] model]; // for current device
if ([deviceType isEqualToString:#"iPhone"])
{
NSString *platform = [self platformRawString];
NSLog(#"platform :%#",platform);
// To set the half cut in the last cell.
if ([platform isEqualToString:#"iPhone2,1"])
//cellHeight = 39.5;
else if ([platform isEqualToString:#"iPhone4,1"])
//cellHeight = 42;
else if ([platform isEqualToString:#"iPhone5,3"] || [platform isEqualToString:#"iPhone5,4"])
//cellHeight = 42.5;
else
//cellHeight = 40.0;
}
Method for getting platform
- (NSString *)platformRawString
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithUTF8String:machine];
free(machine);
return platform;
}
There is an app called "Activity Monitor Touch" in the App Store, which displays background processes as well as free memory.
So there MUST be an public API to access this information. The evidence:
I'm already searching for days but can't find any good starting point. How can this app figure all this stuff out without any jailbreaking / hacking / etc.?
Until recently I was sure that something like this is absolutely impossible on iOS.
I've found this code snippet:
- (NSArray *)runningProcesses {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
NSString * processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString * processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName", nil]];
[processID release];
[processName release];
[array addObject:dict];
[dict release];
}
free(process);
return [array autorelease];
}
}
}
return nil;
}
But I can't make it run on the iPhone. Xcode doesn't know these symbols:
CTL_KERN, KERN_PROC, KERN_PROC_ALL
So of course I must import a header file or library. Does anyone know where these belong to, and how the headers must be imported to make this work?
Works like a charm:
#import <sys/sysctl.h>
sysctl is no longer accessible to sandboxed iOS 9 apps.
From WWDC 2015 session 703 Privacy and Your App:
In iOS 9, the sandbox now prevents a process from accessing the
kern.proc, kern.procargs, and kern.procargs2 values for other
processes
and
iOS apps are not permitted to see what other apps are running
So even if you find a way, you are likely to get rejected from the App Store.
https://developer.apple.com/videos/play/wwdc2015-703/