whats I missed?
NSString * configPath = nil;
-(IBAction)setPlistPathAndWriteData:(id)sender{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setDirectory:#"/Volumes/"];
[panel setNameFieldStringValue:#"config.plist"];
[panel setRequiredFileType:#"plist"];
NSInteger ret = [panel runModal];
if ( ret == NSFileHandlingPanelOKButton ) {
NSString *filePath= [[panel URL] path];
// with this works fine
//configPath = [NSString stringWithFormat:#"/Volumes/Macintosh HD/config.plist"];
// with this EXC BAD ACCESS
configPath = [NSString stringWithFormat:#"%#", filePath];
[self writeData];
}
}
-(void)writeData {
SET_TEMP_PLIST
NSTask *task = [[NSTask alloc] init];
NSPipe *pipe = [[NSPipe alloc] init];
NSFileHandle *writeHandle = [pipe fileHandleForWriting];
NSData *configData = [NSPropertyListSerialization dataFromPropertyList:tmpPlist format:
NSPropertyListXMLFormat_v1_0 errorDescription:nil];
[task setLaunchPath:#"/usr/libexec/authopen"];
////////////////////////////////////////////////////////EXC_BAD_ACCESS HERE////////
[task setArguments:[NSArray arrayWithObjects:#"-c", #"-w", configPath, nil]];
[task setStandardInput:pipe];
[writeHandle writeData:configData];
[task launch];
close([writeHandle fileDescriptor]);
[task waitUntilExit];
[task release];
}
EDIT
well... works fine with this code:
NSString *filePath= [[[panel URL] path] retain];
const char * cString = [filePath UTF8String];
configPath = [[NSString stringWithUTF8String:cString] retain];
but this is not perfect method.. thought
Your app crashes likely because configPath is nil, and later in writeData you try to initialize a new array with nil as the third object :
[NSArray arrayWithObjects:#"-c", #"-w", configPath, nil]
// ^^^ this is nil
I suggest you copy the string returned by path :
if(ret == NSFileHandlingPanelOKButton ) {
// you become the owner of the string,
// don't forget to release configPath later
configPath = [[[panel URL] path] copy];
[self writeData];
}
This may run without any problem.
Related
I am trying to schedule a shutdown event with pmset executed via NSTask in OSX app.
NSCalendar *cal = [NSCalendar new];
NSDate *dateNext = [date dateByAddingTimeInterval:120];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MM/dd/YYYY HH:mm:ss"];
NSString* dS = [df stringFromDate:dateNext];
//# pmset schedule shutdown "MM/DD/YYYY HH:MM:SS"
NSString* dateString = [NSString stringWithFormat:#"\"%#\"", dS];
NSLog(#"Date to set %#", dateString);
int pid = [[NSProcessInfo processInfo] processIdentifier];
NSPipe *pipe = [NSPipe pipe];
NSFileHandle *file = pipe.fileHandleForReading;
NSTask *task = [[NSTask alloc] init];
task.launchPath = #"/usr/bin/pmset";
NSArray *args = [NSArray arrayWithObjects:#"schedule",#"shutdown", dateString, nil];
[task setArguments:args];
task.standardOutput = pipe;
[task launch];
NSData *data = [file readDataToEndOfFile];
[file closeFile];
NSString *out = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"Result:\n%#", out);
The log shows as follows:
2019-09-12 12:38:53.470793+0100 TheApp[51008:4925389] Date to set "09/12/2019 12:40:53"
2019-09-12 12:38:53.518372+0100 TheApp[51008:4925389] Result:
Error: Badly formatted date (2)
Error parsing scheduled event.
The dateString argument seems to be correctly formatted between quotes, as required by pmset, but I keep getting such error. Is there some parameter missing in NSTask?
Thank you.
From the Terminal, I can call all of the Salesforce DX CLI commands and functions. For example, "sfdx force:doc:commands:list" will show all the commands. BUT from the NSTask code (below) on a mac, I cannot call the Salesforce DX CLI at all. The terminationStatus flag is true. Other commands like "ls" work fine. Is this because of paths? permissions? Thanks in advance...
ptr portcommandlineinterface(char *thecommand)
{
ptr theptr;
NSTask *task;
NSPipe *pipe;
NSData *data;
NSFileHandle *file;
NSArray *arguments;
int thesize, status;
const char *junkptr;
NSString *string, *tempstring;
tempstring = [NSString stringWithUTF8String:thecommand];
if (tempstring == 0) return(0);
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
[task setCurrentDirectoryPath: #"~"];
arguments = [NSArray arrayWithObjects: #"-c", tempstring, nil];
[task setArguments: arguments];
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
file = [pipe fileHandleForReading];
[task launch];
[task waitUntilExit];
status = [task terminationStatus];
if (status) return(0);
data = [file readDataToEndOfFile];
string = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
junkptr = [string UTF8String];
thesize = cstrlen((char *)junkptr);
theptr = portnewptr(thesize + 10);
cstrcpy((char *)junkptr, theptr);
return(theptr);
}
I am very new to develop mac osx application using xcode. I am trying to get all running application list with their memory usage.
Can any body help me in this case.
Please help me.
Thanks in advance.
It will help you to get list of running application :
for (NSRunningApplication *app in [[NSWorkspace sharedWorkspace] runningApplications]) {
NSLog(#"%#",[app localizedName]);
}
You may get the cpu usage as:
- (NSString*) get_process_usage:(int) pid
{
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath:#"/bin/ps"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: #"-O",#"%cpu",#"-p",[NSString stringWithFormat:#"%d",pid], nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSString* temp = [string stringByReplacingOccurrencesOfString:#"PID %CPU TT STAT TIME COMMAND" withString:#""];
NSMutableArray* arr =(NSMutableArray*) [temp componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[arr removeObject:#""];
[string release];
[task release];
if([arr count]>=2)
return [arr objectAtIndex:1];
else
return #"unknown";
}
I am trying to change the desktop image; the procedure I've come up with is below. The first time this code is run, the resized image is displayed on screen as wallpaper, but the next time there is no reaction. What am I doing wrong?
-(IBAction)click:(id)sender
{
NSData *sourceData;
NSError *error;
NSFileManager *filemgr;
filemgr = [NSFileManager defaultManager];
screenArray = [NSScreen screens];
screenCount = [screenArray count];
unsigned index = 0;
for (index; index < screenCount; index++)
{
screenz = [screenArray objectAtIndex: index];
screenRect = [screenz visibleFrame];
}
NSLog(#"%fx%f",screenRect.size.width, screenRect.size.height);
arrCatDetails = [strCatDetails componentsSeparatedByString:appDelegate.strColDelimiter];
NSString *imageURL = [NSString stringWithFormat:#"upload/product/image/%#_%#_%d.jpg",[arrCatDetails objectAtIndex:0],appDelegate.str104by157Name,iSelectedImgIndex];
NSString *ima = [imageURL lastPathComponent];
NSString *str = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *dataFilePath = [str stringByAppendingPathComponent:ima];
NSString *imagePath = [NSString stringWithFormat:#"file://localhost%#",dataFilePath];
NSURL *url = [[NSURL alloc] init];
url = [NSURL URLWithString:imagePath];
sourceData = [NSData dataWithContentsOfURL:url];
sourceImage = [[NSImage alloc] initWithData: sourceData];
resizedImage = [[NSImage alloc] initWithSize: NSMakeSize(screenRect.size.width, screenRect.size.height)];
NSSize originalSize = [sourceImage size];
[resizedImage lockFocus];
[sourceImage drawInRect: NSMakeRect(0, 0, screenRect.size.width, screenRect.size.height) fromRect: NSMakeRect(0, 0, originalSize.width, originalSize.height) operation: NSCompositeSourceOver fraction: 1.0];
[resizedImage unlockFocus];
NSData *resizedData = [resizedImage TIFFRepresentation];
NSBitmapImageRep* theImageRepresentation = [NSBitmapImageRep imageRepWithData:resizedData];
newimage = #"editwall.jpg";
newFilePath = [str stringByAppendingPathComponent:newimage];
NSData* theImageData = [theImageRepresentation representationUsingType:NSJPEGFileType properties:nil];
[theImageData writeToFile: newFilePath atomically: YES];
if([filemgr fileExistsAtPath:newFilePath] == YES)
{
imagePath1 = [NSString stringWithFormat:#"file://localhost%#",newFilePath];
urlz = [NSURL URLWithString:imagePath1];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:nil, NSWorkspaceDesktopImageFillColorKey, [NSNumber numberWithBool:NO], NSWorkspaceDesktopImageAllowClippingKey, [NSNumber numberWithInteger:NSImageScaleProportionallyUpOrDown], NSWorkspaceDesktopImageScalingKey, nil];
[[NSWorkspace sharedWorkspace] setDesktopImageURL:urlz forScreen:[[NSScreen screens] lastObject] options:options error:&error];
}
else
{
NSLog(#"No");
}
[sourceImage release];
[resizedImage release];
}
Why not try -[NSWorkspace setDesktopImageURL:forScreen:options:error:]? Apple has a sample project called DesktopImage to give you some idea how to use it.
Edit (after reading your code more carefully):
The problem you're having may be because of your call to +[NSDictionary dictionaryWithObjectsAndKeys:] See the nil at the end of the list of arguments? That's how you tell NSDictionary that your argument list is done. You can't put nil in the list, because it will stop reading the list at that point. If you want to specify a key that has no value, you have to use [NSNull null].
An aside: you've got a memory management issue in your code:
// allocates memory for an NSURL
NSURL * url = [[NSURL alloc] init];
// allocates more memory for an NSURL, and leaks
// the earlier allocation
url = [NSURL URLWithString:imagePath];
Just do one or the other:
// If you do it this way, you will have to call
// [url release] later
NSURL * url = [[NSURL alloc] initWithString:imagePath];
// This memory will be released automatically
NSURL * otherUrl = [NSURL URLWithString:imagePath];
I've been spending the last few hours trying to find the memory leak in my code. Here it is:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
expression = [expression stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]]; // expression is an NSString object.
NSArray *arguments = [NSArray arrayWithObjects:expression, [#"~/Desktop/file.txt" stringByExpandingTildeInPath], #"-n", #"--line-number", nil];
NSPipe *outPipe = [[NSPipe alloc] init];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/usr/bin/grep"];
[task setArguments:arguments];
[task setStandardOutput:outPipe];
[outPipe release];
[task launch];
NSData *data = [[outPipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
[task release];
NSString *string = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
string = [string stringByReplacingOccurrencesOfString:#"\r" withString:#""];
int linesNum = 0;
NSMutableArray *possibleMatches = [[NSMutableArray alloc] init];
if ([string length] > 0) {
NSArray *lines = [string componentsSeparatedByString:#"\n"];
linesNum = [lines count];
for (int i = 0; i < [lines count]; i++) {
NSString *currentLine = [lines objectAtIndex:i];
NSArray *values = [currentLine componentsSeparatedByString:#"\t"];
if ([values count] == 20)
[possibleMatches addObject:currentLine];
}
}
[string release];
[pool release];
return [possibleMatches autorelease];
I tried to follow the few basic rules of Cocoa memory management, but somehow there still seems to be a leak, I believe it's an array that's leaking. It's noticeable if possibleMatches is large. You can try the code by using any large file as "~/Desktop/file.txt" and as expression something that yields many results when grep-ing.
What's the mistake I'm making?
Thanks for any help!
-- Ry
EDIT: I just used the Clang Static Analyzer to find leaks in my code, but it doesn't find any. It only finds dead initializations, but those can't be responsible for my leaks...
Here:
NSString *string = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
string = [string stringByReplacingOccurrencesOfString:#"\r" withString:#""];
You're overwriting the string object pointer without releasing or autoreleasing the original string. Instead of releasing string at the end of the method, do:
NSString *string = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease];
string = [string stringByReplacingOccurrencesOfString:#"\r" withString:#""];
A probable route to a solution is to use Instruments' Leaks template. By setting the inspection range to start just before this code, then looking at which allocations are still alive after this code has returned, you can see what got leaked, and then look at the leaks' pointer histories and the corresponding stack traces to see exactly what happened.