How to add file contents by dragging that file - objective-c

I am using the following code to perform drag operation on NSTextView object.
- (BOOL)performDragOperation:(id )sender
{
NSPasteboard *pboard = [sender draggingPasteboard];
if ( [[pboard types] containsObject:NSURLPboardType] )
{
NSURL *fileURL = [NSURL URLFromPasteboard:pboard];
if ([[fileURL path] hasSuffix:#"plist"])
{
NSString *code = [NSString stringWithContentsOfURL:fileURL encoding:NSUTF8StringEncoding error:NULL];
int cnt = [[self string] length];
if (cnt) [self setSelectedRange:NSMakeRange(0, cnt)];
[self insertText:code];
return YES;
}
}
return NO;
}
I have declared this method in the .h file as well.
But after running the code it showing following warnings.
warning: 'AppConroller' may not respond to '-string'
(Messages without a matching method signature will be assumed to return 'id' and accept'...' as arguments.)
warning: 'AppConroller' may not respond to '-setSelectedRange:'
warning: 'AppConroller' may not respond to '-insertText:'

You're sending self (the AppController) messages it doesn't support. I think you mean to have [sender string], [sender setSelectedRange:], and [sender insertText:].

Is it possible it's just a typo? All your warnings refer to "AppConroller", but I bet the class is actually named "AppController".

Related

Accept drag'n'drop from iPhoto or Aperture

I've created an app, containing an ImageView subclass which accepts drag'n'dropping files/folders directly from Finder.
The thing is I'm now trying to make it accept photos, either from iPhoto or Aperture, as well.
Which PboardTypes should I register for?
All I'm currently doing is :
[self registerForDraggedTypes:
[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
Any ideas?
Using Pasteboard Peeker (from Apple) shows me that Aperture gives you file names/URLs as well as "aperture image data" (whatever that is). iPhoto appears only to give "ImageDataListPboardType", which is a PLIST. I'm guessing you could NSLog() that out to see its structure and pull the image information from it. It may possibly include the filename/URL info as well as the actual image as data.
You are correct to register for NSFilenamesPboardType. To complete the task:
1: Make sure you accept the copy operation in draggingEntered. The generic operation is insufficient.
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
NSDragOperation sourceDragMask = [sender draggingSourceOperationMask];
NSPasteboard *pasteboard = [sender draggingPasteboard];
if ( [[pasteboard types] containsObject:NSFilenamesPboardType] ) {
if (sourceDragMask & NSDragOperationCopy) {
return NSDragOperationCopy;
}
}
return NSDragOperationNone;
}
2: There will be one filename per photo. Do something with them.
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
NSPasteboard *pasteboard;
NSDragOperation sourceDragMask;
sourceDragMask = [sender draggingSourceOperationMask];
pasteboard = [sender draggingPasteboard];
if ([[pasteboard types] containsObject:NSFilenamesPboardType])
{
NSData* data = [pasteboard dataForType:NSFilenamesPboardType];
if(data)
{
NSString *errorDescription;
NSArray *filenames = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:kCFPropertyListImmutable format:nil errorDescription:&errorDescription];
for (NSString* filename in filenames)
{
NSImage* image = [[NSImage alloc]initWithContentsOfFile:filename];
//Do something with the image
}
}
}
return YES;
}

How to convert NSUrl to NSString?

After AVAssetExportSession has complete export video.
I have plan to garb Video Path to upload via Youtube.
but [GDataUtilities MIMETypeForFileAtPath:path defaultMIMEType:#"video/mp4"];
it only accept NSString.
Is it possible to convert NSUrl in to NSString for video file path.
i have try to use NSString *path = [ExportoutputURL absoluteString];
but it crash.
Here is the Code
- (void)exportDidFinish:(AVAssetExportSession*)session {
ExportoutputURL = session.outputURL;
_exporting = NO;
NSIndexPath *exportCellIndexPath = [NSIndexPath indexPathForRow:2 inSection:kProjectSection];
ExportCell *cell = (ExportCell*)[self.tableView cellForRowAtIndexPath:exportCellIndexPath];
cell.progressView.progress = 1.0;
[cell setProgressViewHidden:YES animated:YES];
[self updateCell:cell forRowAtIndexPath:exportCellIndexPath];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:ExportoutputURL]) {
[library writeVideoAtPathToSavedPhotosAlbum:ExportoutputURL
completionBlock:^(NSURL *assetURL, NSError *error){
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(#"writeVideoToAssestsLibrary failed: %#", error);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription]
message:[error localizedRecoverySuggestion]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
else {
_showSavedVideoToAssestsLibrary = YES;
ExportCell *cell = (ExportCell*)[self.tableView cellForRowAtIndexPath:exportCellIndexPath];
[cell setDetailTextLabelHidden:NO animated:YES];
[self updateCell:cell forRowAtIndexPath:exportCellIndexPath];
NSArray *modes = [[[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, UITrackingRunLoopMode, nil] autorelease];
[self performSelector:#selector(hideCameraRollText) withObject:nil afterDelay:5.0 inModes:modes];
}
});
}];
}
[library release];
}
- (void)uploadVideoFile {
NSString *devKey = DEVELOPER_KEY;
GDataServiceGoogleYouTube *service = [self youTubeService];
[service setYouTubeDeveloperKey:devKey];
NSURL *url = [GDataServiceGoogleYouTube youTubeUploadURLForUserID:kGDataServiceDefaultUser];
// load the file data
NSString *path = [ExportoutputURL absoluteString];//[[NSBundle mainBundle] pathForResource:#"video_2451" ofType:#"mp4"];//[mFilePathField stringValue];
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
NSString *filename = [path lastPathComponent];
// gather all the metadata needed for the mediaGroup
NSString *titleStr = #"Upload Test";//[mTitleField stringValue];
GDataMediaTitle *title = [GDataMediaTitle textConstructWithString:titleStr];
NSString *categoryStr = #"Entertainment";//[[mCategoryPopup selectedItem] representedObject];
GDataMediaCategory *category = [GDataMediaCategory mediaCategoryWithString:categoryStr];
[category setScheme:kGDataSchemeYouTubeCategory];
NSString *descStr = #"GData Description";//[mDescriptionField stringValue];
GDataMediaDescription *desc = [GDataMediaDescription textConstructWithString:descStr];
NSString *keywordsStr = #"RAGOpoR Demo";//[mKeywordsField stringValue];
GDataMediaKeywords *keywords = [GDataMediaKeywords keywordsWithString:keywordsStr];
BOOL isPrivate = NO;//([mPrivateCheckbox state] == NSOnState);
GDataYouTubeMediaGroup *mediaGroup = [GDataYouTubeMediaGroup mediaGroup];
[mediaGroup setMediaTitle:title];
[mediaGroup setMediaDescription:desc];
[mediaGroup addMediaCategory:category];
[mediaGroup setMediaKeywords:keywords];
[mediaGroup setIsPrivate:isPrivate];
NSString *mimeType = [GDataUtilities MIMETypeForFileAtPath:path
defaultMIMEType:#"video/mp4"];
// create the upload entry with the mediaGroup and the file
GDataEntryYouTubeUpload *entry;
entry = [GDataEntryYouTubeUpload uploadEntryWithMediaGroup:mediaGroup
fileHandle:fileHandle
MIMEType:mimeType
slug:filename];
SEL progressSel = #selector(ticket:hasDeliveredByteCount:ofTotalByteCount:);
[service setServiceUploadProgressSelector:progressSel];
GDataServiceTicket *ticket;
ticket = [service fetchEntryByInsertingEntry:entry
forFeedURL:url
delegate:self
didFinishSelector:#selector(uploadTicket:finishedWithEntry:error:)];
[self setUploadTicket:ticket];
GTMHTTPUploadFetcher *uploadFetcher = (GTMHTTPUploadFetcher *)[ticket objectFetcher];
}
Error EXC_BAD_ACCESS at
NSString *path = [ExportoutputURL absoluteString];
Is it possible to convert NSUrl in to NSString for video file path.
Yes. Send it an absoluteString message.
i have try to use NSString *path = [ExportoutputURL absoluteString]; but it crash.
If you want a path, send the URL a path message. A string representing a URL is generally not a valid path; if you want a path, ask it for one.
As for the crash, it does not mean absoluteString is wrong. Sending absoluteString to an NSURL object is the correct way to get an NSString object that represents the URL. The problem is somewhere else.
Error EXC_BAD_ACCESS at
NSString *path = [ExportoutputURL absoluteString];
This probably means that ExportoutputURL points to something that is not nil but is also not a valid object. It might have pointed to an NSURL object at some point, but it doesn't now.
My guess would be that the problem is this:
ExportoutputURL = session.outputURL;
You assign the URL to the ExportoutputURL instance variable, but you don't retain the object or make your own copy. Therefore, you don't own this object, which means you are not keeping it alive. It may die at any time, most probably after this method (exportDidFinish:) returns.
The crash is because you call uploadVideoFile later, after the URL object has already died. You still have a pointer to it, but that object no longer exists, so sending a message to it—any message—causes a crash.
There are three simple solutions:
Retain the URL object when you assign it to your instance variable.
Make your own copy of the URL object and assign that to the instance variable.
Declare ExportoutputURL as a property, with either the strong keyword or the copy keyword, and assign the object to the property, not the instance variable. That will call the property's setter, which, if you synthesize it or implement it correctly, will retain or copy the URL for you.
Either way, you will own the object, and that will keep it alive until you release it. Accordingly, you will need to release it when you are done with it (in dealloc, if not earlier), so that you don't leak it.
This all assumes that you are not using ARC. If you are using Xcode 4.2 or later, and can require iOS 4 or later, you should migrate your project to ARC, as it makes so many things much simpler. You would not need to retain or copy this object if you were using ARC, which means that migrating to ARC now is a fourth solution (but certainly a larger-scale one).
Use either absolutePath or path as mentioned by Miek and Nepster. Expanding on their answers, the difference between lies in the prefix.
NSString* string1 = [url absoluteString]; // #"file:///Users/jackbrown/Music/song name.mp3"
NSString* string2 = [url path]; // #"/Users/jackbrown/Music/song name.mp3"`
NSString *path = [[NSString alloc] initWithString:[url path]]; ?
Use this. I think it will help you.
In Objective c
NSString *testString = testUrl.absoluteString;
In Swift
var testString : String = testUrl.absoluteString
Simply you can do it like this.
NSString *myString = [myURL absoluteString];

Objective C memory management issue

I'm having this issue with some objective C code to load the images on a IKImageBrowserView.
I'm following the image browser example from apple, but I still fail at some point and Im guessing its memory management.
Here is some of the code:
/* Our datasource object */
#interface myImageObject : NSObject
{
NSString *_path;
}
#end
#implementation myImageObject
- (void)dealloc
{
[_path release];
[super dealloc];
}
/* our datasource object is just a filepath representation */
- (void)setPath:(NSString *)path
{
NSLog(#"setting path for %#",path);
if(_path != path)
{
[_path release];
_path = [path retain];
}
}
Now, It seems I'm properly retaining the path value within the object.
now on to the controller code:
-(IBAction)loadMosaicImages:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *urls = [openFiles() retain];
NSInteger n;
n = [urls count];
NSURL *url = [urls objectAtIndex:0];
[self parsePathForImages:[url path]];
[urls release];
[pool drain];
}
- (void)updateDatasource
{
NSLog(#" UDS-> _importedImages length : %#",[_importedImages count]);
//-- update our datasource, add recently imported items
[_images addObjectsFromArray:_importedImages];
//-- empty our temporary array
[_importedImages removeAllObjects];
NSLog(#" UDS-> _images length : %#",[_images count]);
//-- reload the image browser and set needs display
[_imageBrowser reloadData];
}
-(void)parsePathForImages:(NSString *)path{
NSLog(#"Directory within thread method is %#",path);
NSArray *content = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
myImageObject *p;
for(int i=0;i<content.count;i++)
{
// NSLog(#"%#",(NSString *)[content objectAtIndex:i]);
NSLog(#"Complete : %#",[path stringByAppendingPathComponent:(NSString *)[content objectAtIndex:i]]);
/* add a path to our temporary array */
p = [[myImageObject alloc] init];
[p setPath:[path stringByAppendingPathComponent:[content objectAtIndex:i]]];
[_importedImages addObject:p];
[p release];
}
[self updateDatasource];
}
and that's all the relevant code. _images and _importedImages are NSMutableArrays alloced and inited in the awake from nib method, and openFiles() is a static method that opens an NSOpenpanel and returns an NSArray of the paths.
the debug output for this does this:
Directory within thread method is /Users/cromestant/Code/images/
Complete : /Users/cromestant/Code/images/1.jpg
setting path for /Users/cromestant/Code/images/1.jpg
Complete : /Users/cromestant/Code/images/2.jpg
setting path for /Users/cromestant/Code/images/2.jpg
Complete : /Users/cromestant/Code/images/3.jpg
setting path for /Users/cromestant/Code/images/3.jpg
.
.
.
then stops crashes at the first line of the method updateDataSource, on the NSLog with an 'EXEC_BAD_ACCESS'so where am I going wrong with the memory management?
I seem to be creating an autoreleasePool so ht I have time to retain somewhere else, I release my objects.. I really don't have a clue where the problem could be.
thanks in advance.
Actually, I think your problem might not be memory management. It might be here:
NSLog(#" UDS-> _importedImages length : %#",[_importedImages count]);
It should be
NSLog(#" UDS-> _importedImages length : %d",[_importedImages count]);
because the count method returns an integer, not an object.

Opening 'New' Document?

I have some code implemented in my myDocument.m file that simply attempts to load the last used document upon launch. However, upon launching from a fresh install, (or running after deleting the last used file) a 'new' document window does not appear. Does anyone know what to add to my code to do this? Here it is:
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
NSURL *lastURL=[[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:lastURL display:YES error:nil];
if (lastURL!=nil)
{
[docController openDocumentWithContentsOfURL:lastURL display:YES error:nil];
return NO;
}
return YES;
}
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
NSArray* urls = [[NSDocumentController sharedDocumentController] recentDocumentURLs];
if ([urls count] > 0){
NSURL *lastURL= [urls objectAtIndex: 0];
if ([[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:lastURL display:YES error:nil]){
return NO;
}
}
return YES;
}
EDIT
I changed it and tried it out it should work now.
What is docController, and why are you sending -openDocumentWithContentsOfURL:display:error: twice? Note that that method returns a document, not a URL, so using the return value as a URL wouldn’t work anyway.
The following is a cleaner, equivalent code:
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
id lastDoc = [[NSDocumentController sharedDocumentController]
openDocumentWithContentsOfURL:lastURL
display:YES error:NULL];
return (lastDoc == nil);
}
However, it still doesn’t explain why you don’t get an untitled document. What happens if you comment out -applicationShouldOpenUntitledFile: so that the application follows standard Cocoa behaviour? It could be the case that the problem lies elsewhere.

ObC : app crashes after returning NSMutableArray?

I am new to ObC and have a problem that i just cant fix. There may be other issues as well but the main issue is this:
Starting the app
Press button = load new view
In the new viewDidLoad i call another object/function and send a NSMutableArray
Process data and send back a NSMutableArray
App crash, see comment where. Most often when i go back and back again but sometimes the first time
As i am new to this i guess i do a lot of this wrong but could someone nice take a look at the code and give me some advice. I would assume i have problem with releasing something.
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#" ");
NSLog(#"viewDidLoad ");
NSLog(#" ");
NSLog(#">>Processing prepareGame<<");
NSMutableArray *propArray1 = [[NSMutableArray alloc] initWithObjects:#"9999", nil]; //Init with dummy numbers
AccessPropertiesFile *readMyProperties = [AccessPropertiesFile new]; //Init function call to read file
NSLog(#"Prepare to call readProperties");
propArray1 = [readMyProperties readPropertiesFile:propArray1];
NSLog(#"Back from readProperties:error after this");
/*
for (NSString *element in propArray1) {
NSLog(#"Elements in prop2Array; %#", element);
}
*/
[readMyProperties release];
[propArray1 release];
}
-(NSMutableArray *)readPropertiesFile:(NSMutableArray *)readDataArray {
NSLog(#"Processing readProperties");
// For error information
NSError *error;
//Prepare File Manager
NSString *filePath = [self dataFilePath];
NSFileManager *fileMgr;
fileMgr = [NSFileManager defaultManager];
NSArray *propertiesArray = [NSArray alloc]; //Alloc array
//Check from what module the call is coming from to ecide what to do
if ([fileMgr fileExistsAtPath: filePath] == NO) {
NSLog (#"File not found");
//File does not exists, this is the first time the game starts
//Set up default parameters
NSString *fileString =#"0\n30\n30\n10\n1\n1\n1\n2\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n";
// Write default parameters to file
[fileString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
propertiesArray = [fileString componentsSeparatedByString:#"\n"]; // each line, adjust character for line endings
}
else { //File exists
NSLog (#"File exists");
NSString *fileString = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding error:nil]; // reads file into memory as an NSString
propertiesArray = [fileString componentsSeparatedByString:#"\n"]; // each line, adjust character for line endings
}
//Clean readDataArray
[readDataArray removeAllObjects];
//Populate return array
for (NSString *element in propertiesArray) {
//NSLog(#"Elements in propertiesArray; %#", element);
[readDataArray addObject:element];
}
NSLog(#"readDataArray: %#", readDataArray);
[propertiesArray release];
[readDataArray autorelease];
NSLog(#"returning from readProperties");
return readDataArray;
}
#end
You are over-releasing readDataArray (known as propArray1 in the method that didn't create it). You create it and autorelease it in your second method, then you release it again at the end of your first method (where it wasn't created).
I suggest you use Analyze feature that comes with latest XCode. It is a good feature that I always use to track if I forget to release or release too much.
I also spotted that you also over-release the propertiesArray because it contains the result from [fileString componentsSeparatedByString:], which will be autorelease according to Cocoa convention.