How to get selected text from dragging? - objective-c

To detect file name from file, I use code below with success.
file .h :
#interface DropView : NSView <NSDraggingDestination>
file .m
init :
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
and I implement protocol like this
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender {
NSLog(#"%#", [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType]);
}
It return Null when I dragged some text. (highlight text and dragged from other app)
I have tried to change code from
propertyListForType:NSFilenamesPboardType to propertyListForType:NSStringPboardType or propertyListForType:NSPasteboardTypeString
but no luck.
Please help me how to get only selected text?
Thank you.
I have found the solution, Just declare NSPasteboard from sender and get string for type NSStringPboardType
NSPasteboard *pboard = [sender draggingPasteboard];
NSString *string = [pboard stringForType:NSStringPboardType];
Cheer!!

Related

Objective-C delegate incompatible type

I am using http://www.vfr.org/, pdf viewer, and I try to add a button to open PDF in IBOOK.
I added the button and action to it, but I stuck t the moment when I want open ibooks application with this pdf.
I tried 2 solutions:
button tapped action:
NSURL *fileURL = document.fileURL;
NSString *fileName = document.fileName; // Document
[[UIApplication sharedApplication] openURL:fileURL];
It opens the IBOOKS but the PDF never gets loaded.
I am assuming the URL format can be wrong I tried even hard code a PDF URL like:
NSString *stringURL = #"itms-books://linktopdf.pdf";
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
But the same result.
2) Button tapped action:
NSURL *fileURL = document.fileURL;
NSString *fileName = document.fileName; // Document
UIDocumentInteractionController *docController = [[UIDocumentInteractionController alloc] init];
docController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
docController.delegate = self;
But I have an warning where I try to delegate: docController.delegate = self;
assigning to id UIDocumentInteractionControllerDelegate from Incompatible ReaderViewController
Can someone help me to make it work at least 1 of these solution.
Has the ReaderViewController this kind of line in the header file: #interface ReaderViewController : NSObject < UIDocumentInteractionControllerDelegate > ?
Your class must conform to the UIDocumentInteractionControllerDelegate protocol, so in your .h file make it look like
#interface ReaderViewController : PerantClass <UIDocumentInteractionControllerDelegate>
{
...
}
Then the compiler will know that your class conforms to that protocol. Of course, you still need to implement the needed methods.
ALso Check this Link - 1 And Link - 2.

ShareKit: Customizing text for different sharers (SHKActionSheet)

According to the official FAQ from ver.2 to customize your text/content depending on what sharer was selected by the user, you need:
subclass from SHKActionSheet and override
dismissWithClickedButtonIndex
set your new subclass name in
configurator (return it in (Class)SHKActionSheetSubclass;).
It doesn't work for me. But even more: I put
NSLog(#"%#", NSStringFromSelector(_cmd));
in (Class)SHKActionSheetSubclass to see if it's even got called. And it's NOT ;(( So ShareKit doesn't care about this config option...
Has anybody worked with this before?
thank you!
UPD1: I put some code here.
Here's how my subclass ITPShareKitActionSheet looks like. According to the docs I need to override dismissWithClickedButtonIndex:animated:, but to track if my class gets called I also override the actionSheetForItem::
+ (ITPShareKitActionSheet *)actionSheetForItem:(SHKItem *)item
{
NSLog(#"%#", NSStringFromSelector(_cmd));
ITPShareKitActionSheet *as = (ITPShareKitActionSheet *)[super actionSheetForItem:item];
return as;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animate
{
NSLog(#"%#", NSStringFromSelector(_cmd));
NSString *sharersName = [self buttonTitleAtIndex:buttonIndex];
[self changeItemForService:sharersName];
[super dismissWithClickedButtonIndex:buttonIndex animated:animate];
}
And here's what I do in code to create an action sheet when user presses 'Share' button:
- (IBAction)shareButtonPressed:(id)sender
{
// Create the item to share
SHKItem *item = [SHKItem text:#"test share text"];
// Get the ShareKit action sheet
ITPShareKitActionSheet *actionSheet = [ITPShareKitActionSheet actionSheetForItem:item];
// Display the action sheet
[actionSheet showInView:self.view]; // showFromToolbar:self.navigationController.toolbar];
}
When I run this code, press 'Share' button and select any sharer I expect to get two lines in log:
actionSheetForItem: - custom action sheet got created
dismissWithClickedButtonIndex:animated: - custom mechanics to
process action sheet's pressed button got called.
But for some reason I get only the first line logged.
I was having the same issues but I've suddenly got it to call my Subclass successfully.
Firstly My Configurator is setup as so:
-(Class) SHKActionSheetSubclass{
return NSClassFromString(#"TBRSHKActionSheet");
}
Now My Subclass:
.h File
#import "SHKActionSheet.h"
#interface TBRSHKActionSheet : SHKActionSheet
#end
.m implementation override:
#import "TBRSHKActionSheet.h"
#import "SHKActionSheet.h"
#import "SHKShareMenu.h"
#import "SHK.h"
#import "SHKConfiguration.h"
#import "SHKSharer.h"
#import "SHKShareItemDelegate.h"
#implementation TBRSHKActionSheet
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
+ (SHKActionSheet *)actionSheetForItem:(SHKItem *)i
{
NSLog(#"%#", NSStringFromSelector(_cmd));
SHKActionSheet *as = [self actionSheetForType:i.shareType];
as.item = i;
return as;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
NSInteger numberOfSharers = (NSInteger) [sharers count];
// Sharers
if (buttonIndex >= 0 && buttonIndex < numberOfSharers)
{
bool doShare = YES;
SHKSharer* sharer = [[NSClassFromString([sharers objectAtIndex:buttonIndex]) alloc] init];
[sharer loadItem:item];
if (shareDelegate != nil && [shareDelegate respondsToSelector:#selector(aboutToShareItem:withSharer:)])
{
doShare = [shareDelegate aboutToShareItem:item withSharer:sharer];
}
if(doShare)
[sharer share];
}
// More
else if ([SHKCONFIG(showActionSheetMoreButton) boolValue] && buttonIndex == numberOfSharers)
{
SHKShareMenu *shareMenu = [[SHKCONFIG(SHKShareMenuSubclass) alloc] initWithStyle:UITableViewStyleGrouped];
shareMenu.shareDelegate = shareDelegate;
shareMenu.item = item;
[[SHK currentHelper] showViewController:shareMenu];
}
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
Finally on my implementation file I've not modified the call to SHKActionSheet as Vilem has suggested because of some dependancies that seemed to cause conflicts for me.
So this is my caller (straight from tutorial):
NSURL *url = [NSURL URLWithString:#"http://getsharekit.com"];
SHKItem *item = [SHKItem URL:url title:#"ShareKit is Awesome!" contentType:SHKURLContentTypeWebpage];
// Get the ShareKit action sheet
SHKActionSheet *actionSheet = [SHKActionSheet actionSheetForItem:item];
// ShareKit detects top view controller (the one intended to present ShareKit UI) automatically,
// but sometimes it may not find one. To be safe, set it explicitly
[SHK setRootViewController:self];
// Display the action sheet
[actionSheet showFromToolbar:self.navigationController.toolbar];
This Calls no problems for me.
edit: by far the best way to achieve this is to use SHKShareItemDelegate. More info is in ShareKit's FAQ.

Can drag and drop file URL text, but not actual file

I'm able to drag a file URL from a NSTableView cell and drop it in any text editor. According to my understanding of Apple's documentation though, when I drop the URL, the file should be copied to the drop location.
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard {
//for now putting specific file path in just to get it working
NSString *filePath = #"/Users/Jackh/Desktop/Apple.png";
[pboard declareTypes:[NSArray arrayWithObject:NSURLPboardType] owner:self];
[[NSURL URLWithString:filePath] writeToPasteboard:pboard];
return YES;
}
How do I get the file to copy from the filePath to the dropped location? It's just moving filePath as text for now.
Any ideas?
Edit: I am now using this code
-(void)awakeFromNib {
[self.tableView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:NO];
}
...
[self.tableView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSFileContentsPboardType, nil]];
...
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard {
//for now putting specific file path in just to get it working
NSString *filePath = #"/Users/Jackh/Desktop/Apple.png";
[pboard declareTypes:[NSArray arrayWithObject:NSFileContentsPboardType] owner:nil];
[pboard writeFileContents:filePath];
}
If you want to force the green "+" to copy, just use NSDragOperationCopy (only) in the operation mask, disallowing other operations; e.g. in awakeFromNib:
[self.tableView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
Here is the best way I could find to make your example work with the Finder:
- (BOOL)
tableView:(NSTableView *)tv
writeRowsWithIndexes:(NSIndexSet*)rowIndexes
toPasteboard:(NSPasteboard*)pboard {
NSString *filePath = #"/Users/kevin/Desktop/1.png";
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
owner:nil];
[pboard setPropertyList:[NSArray arrayWithObject:filePath]
forType:NSFilenamesPboardType];
return YES;
}
Note that Apple recommends using more modern APIs but I have found in cases like this they have a big side effect: they seem to cause files to be copied twice because URLs are magically copied in multiple forms. Having said that, your original URL example didn't work because you should have used writeObjects: on the pasteboard instead of asking the URL to writeToPasteboard:. An example with URLs:
- (BOOL)
tableView:(NSTableView *)tv
writeRowsWithIndexes:(NSIndexSet*)rowIndexes
toPasteboard:(NSPasteboard*)pboard {
NSString *filePath = #"/Users/kevin/Desktop/1.png";
[pboard declareTypes:[NSArray arrayWithObject:NSURLPboardType]
owner:nil];
[pboard writeObjects:[NSArray arrayWithObject:
[NSURL fileURLWithPath:filePath]]];
return YES;
}
As I noted in other comments, if your drag is targeting a document instead of a file manager such as the Finder then it's better to include the actual data for the file. Raw data can't be misinterpreted by a document (i.e. the document has to insert the data directly, it can't choose to insert a path string instead). On the other hand, raw-data drags don't create files in the Finder for some reason so they're useful mainly as something to add to the pasteboard as an alternative.
Here is a way to use a UTI to declare the file type and call NSData to read a file (I tried this and it works, e.g. I can drag a table view row into a Rich Text document in TextEdit and see an image inserted into the window):
- (BOOL)
tableView:(NSTableView *)tv
writeRowsWithIndexes:(NSIndexSet*)rowIndexes
toPasteboard:(NSPasteboard*)pboard {
NSString *filePath = #"/Users/kevin/Desktop/1.png";
[pboard declareTypes:[NSArray arrayWithObject:#"public.png"]
owner:nil];
[pboard setData:[NSData dataWithContentsOfFile:filePath]
forType:#"public.png"];
return YES;
}
(I don't know exactly why your writeFileContents: doesn't work but the above does work and is basically the same thing.)

How to get image file path from UIImageview

I have a UIImageView that diaplays an image. Then I have a button titled 'save' . What I want to do is that when I click the button, it should save the image file name into a plist for further retrieval and stuff.
I know how to save into plist and all. The problem is only that I don't know how to get the file path of the image being displayed in the UIImageView.
I did homework and found few articles but im still confused. Any help will be appreciated.
I dont think it is possible to get the image path from a UIImage, if by path you mean the original location on disk, then i dont think that you can do it
The best way to do this is to Save the image in document folder with name image1, image2, etc or the exact name of the image if you know it. And you can save the image names in the plist. Using the names here you can do the further stuff easily.
Create UIImageview as CustomImageview class with NSString variable.Then while showing that image,store the image file path in that string variable.Then you can get it where ever you want with the use of that string.Use the following code
#import <UIKit/UIKit.h>
#interface Imager : UIImageView
{
NSString* imageFileName; #property(nonatomic,retain)NSString* imageFileName;
}
#end
#import "Imager.h"
#implementation
#synthesize imageFileName
and the assign the filepathname where you are assigning the image like your
Imageview.image = UIImage;
your Imageview.imageFileName=yourImageFilepath;
to get the yourImageFilepath add "AssetsLibrary.framework" to your framework folder.Then add #import "AssetsLibrary/AssetsLibrary.h"; to the header file of your class.
then add the following code in "didFinishPickingMediaWithInfo" method
UIImage *viewImage = yourImage;
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum:[viewImage CGImage] orientation: (ALAssetOrientation)[viewImage imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
NSLog(#"error");
}
else
{
NSLog(#"url %#", assetURL);
}
}];
[library release];
It will return a url.that is your yourImageFilepath.

asyncudpsocket does not send UDP as expected

I have XCODE 3.1.4 running ona mini MAC 10.5.8 and Simulator 3.1
I want to send a short UDP string for some remote control and have made the following code
Basicly it does compile and run in the simulator ... but it nevers send any UDP to the target. I hope someone can give me a clue why it does not work
My .H code
#import <UIKit/UIKit.h>
#import "AsyncUdpSocket.h"
#import "AsyncSocket.h"
#interface ChangeLabelViewController : UIViewController {
IBOutlet UILabel *label ;
AsyncUdpSocket *socket;
}
-(IBAction) ChangeLabel;
-(IBAction) ResetLabel;
#end
My .m code
#import "ChangeLabelViewController.h"
#implementation ChangeLabelViewController
-(IBAction) ChangeLabel
{
label.text = #"Hello";
}
-(IBAction) ResetLabel
{
label.text = #"Empty";
NSLog(#"%s", __PRETTY_FUNCTION__);
NSString * string = #"Testing iPhone";
NSString * address = #"192.168.1.11";
UInt16 port = 1234;
NSData * data = [string dataUsingEncoding: NSUTF8StringEncoding];
if ([socket sendData:data toHost:address port:port withTimeout:- 1 tag:1]) label.text = #"Send";
// if ([socket sendData:data toHost:address port:port withTimeout:-1 tag:1] == YES) label.text = #"Yes";
// if ([socket sendData:data toHost:address port:port withTimeout:-1 tag:1] == NO) then label.text = #"No";
;
}
#end
Had to init the socket
under - (void) vievDidLoad
socket = [[AsyncUdpSocket alloc] initWithDelegate:self];
Then it worked as expected :-)
If you are staring from a brand new project you will also need to do the following:
1. add CFNetwork to your frameworks in the project
2. add the cocaasyncsockets files to your project
Instructions are here: http://code.google.com/p/cocoaasyncsocket/wiki/iPhone
Pay attention to the instructions on how to add CFNetwork, it is not shown in the list of available options.
Hint: you will need to use the finder to select a path, I am a mac novice so it took me a while to figure out that I had to use Go/Go To Folder....