Retrieve Data From NSTextView - cocoa

I have an Editable NSTextView,In which user will write using different font style, on certain action i need to prepare the HTML Formate of it,
Can anyone suggest me, how i can retrieve the data from NSTextView,
I am able to use
[[pInputText textStorage] words];
but it returns NSArray, from which i am not able to get NSMutableString,
Can anyone suggest me the best possible way to retrieve the String/data what user typed and in which format.

Below solutions works for me,
- (NSString *)convertUnderlineTextToHTML:(NSAttributedString *)_mString
{
NSArray * exclude = [NSArray arrayWithObjects:#"doctype", #"html",
#"head", #"body",#"xml",nil];
NSDictionary * htmlAtt = [NSDictionary
dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType,NSDocumentTypeDocumentAttribute,exclude,NSExcludedElementsDocumentAttribute,nil];
NSError * error;
NSData * htmlData = [_mString dataFromRange:NSMakeRange(0, [_mString
length]) documentAttributes:htmlAtt error:&error];
NSString * sdat = [[NSString alloc] initWithData:htmlData
encoding:NSUTF8StringEncoding];
NSLog(sdat);
return sdat;
}
Where _mString is
NSMutableAttributedString *pAttributedString = [pInputText textStorage];
NSString *pHtml = [self convertUnderlineTextToHTML:pAttributedString];
Regards
Rohan

NSTextView inherits from NSText, which has a -string method. So [pInputText string should do what you want.
Alternately, TextStorage is a subclass of NSMutableAttributedString, so if you want an attributed string you can just use the return of [pInputText textStorage] directly.

since NSTextStorage is a subclass of NSMutableAttributedString which has a method through its superclass NSAttributedString :initWithHTML:baseURL:documentAttributes, you can use this to get what you want. documentAttributes can be NULL.

Related

post an object to ASP.NET Web API using AFNetworking

the question is simple but I saw the implementation is fairly awkward!!
I want to post an object e.g. Device object to web api web service
// Initialize Client
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://rezawebapi.com"]];
//Indicationg this device is online and sending its dEVICE token to the server
Device *device = [Device new];
device.DeviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"devicetoken"];
device.IsOnline = #"True";
//updating current active users of this app in the server
NSDictionary *dictionary = [[NSDictionary alloc]initWithObjectsAndKeys:
device.DeviceToken,#"DeviceToken",
device.IsOnline,#"IsOnline",
nil];
client.parameterEncoding = AFJSONParameterEncoding;
[client postPath:#"/api/iosAppstats" parameters:dictionary success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSLog(#"%#", responseObject);
// it crashes on the next line because responseObject is NSData
}failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"%#", error.localizedDescription);
}];
1- is there anyway to send the object without creating an dictionary ?(it is error prone!)
2- when my deviceToken is null the object which it sends to the server is null. but consider here one property deviceToken is null but other properties have their own values! does anyone have any idea?
3- I have defined #property (assign, nonatomic) BOOL IsOnline; but when It creates the dictionary EXEX-BAD-ACCESS rises! how should I define bool value? (I had to define it as NSString. it is not an approved way)
1.
is there anyway to send the object without creating an dictionary ?(it is error prone!)
Your API takes JSON. JSON is just dictionaries, arrays, strings, and numbers. So, no. However, it is not error-prone. Just make sure to only put JSON-compliant objects in your dictionary. Read the NSJSONSerialization Overview for more info.
2.
when my deviceToken is null the object which it sends to the server is null. but consider here one property deviceToken is null but other properties have their own values! does anyone have any idea?
You could add deviceToken conditionally, like so:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSString *deviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"devicetoken"];
if (deviceToken) {
[dictionary setObject:deviceToken forKey:#"DeviceToken"];
}
3.
I have defined #property (assign, nonatomic) BOOL IsOnline; but when It creates the dictionary EXEX-BAD-ACCESS rises! how should I define bool value? (I had to define it as NSString. it is not an approved way)
Using a BOOL violates this rule from the NSJSONSerialization overview I linked to in #1:
All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.
So if your property is a BOOL or other simple numerical type, wrap it in #() to make it an NSNumber:
[dictionary setObject:#(device.IsOnline) forKey:#"DeviceToken"];
This is the same as:
NSNumber *isOnlineNum = [NSNumber numberWithBool:device.isOnline];
[dictionary setObject:isOnlineNum forKey:#"DeviceToken"];

NSPopupButton in view based NSTableView: getting bindings to work

Problem Description
I'm trying to achieve something that should be simple and fairly common: having a bindings populated NSPopupButton inside bindings populated NSTableView. Apple describes this for a cell based table in the their documentation Implementing To-One Relationships Using Pop-Up Menus and it looks like this:
I can't get this to work for a view based table. The "Author" popup won't populate itself no matter what I do.
I have two array controllers, one for the items in the table (Items) and one for the authors (Authors), both associated with the respective entities in my core data model. I bind the NSManagedPopup in my cell as follows in interface builder:
Content -> Authors (Controller Key: arrangedObjects)
Content Values -> Authors (Controller Key: arrangedObjects, Model Key Path: name)
Selected Object -> Table Cell View (Model Key Path: objectValue.author
If I place the popup somewhere outside the table it works fine (except for the selection obviously), so I guess the binding setup should be ok.
Things I Have Already Tried
Someone suggested a workaround using an IBOutlet property to the Authors array controller but this doesn't seem to work for me either.
In another SO question it was suggested to subclass NSTableCellView and establish the required connections programmatically. I tried this but had only limited success.
If I setup the bindings as follows:
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
if ([tableColumn.identifier isEqualToString:#"Author") {
AuthorSelectorCell *authorSelectorCell = (AuthorSelectorCell *)view;
[authorSelectorCell.popupButton bind:NSContentBinding toObject:self.authors withKeyPath:#"arrangedObjects" options:nil];
[authorSelectorCell.popupButton bind:NSContentValuesBinding toObject:self.authors withKeyPath:#"arrangedObjects.name" options:nil];
[authorSelectorCell.popupButton bind:NSSelectedObjectBinding toObject:view withKeyPath:#"objectValue.author" options:nil];
}
return view;
}
the popup does show the list of possible authors but the current selection always shows as "No Value". If I add
[authorSelectorCell.popupButton bind:NSSelectedValueBinding toObject:view withKeyPath:#"objectValue.author.name" options:nil];
the current selection is completely empty. The only way to make the current selection show up is by setting
[authorSelectorCell.popupButton bind:NSSelectedObjectBinding toObject:view withKeyPath:#"objectValue.author.name" options:nil];
which will break as soon as I select a different author since it will try to assign an NSString* to an Author* property.
Any Ideas?
I had the same problem. I've put a sample project showing this is possible on Github.
Someone suggested a workaround using an IBOutlet property to the Authors
array controller but this doesn't seem to work for me either.
This is the approach that did work for me, and that is demonstrated in the sample project. The missing bit of the puzzle is that that IBOutlet to the array controller needs to be in the class that provides the TableView's delegate.
Had the same problem and found this workaround - basically get your authors array controller out of nib with a IBOutlet and bind to it via file owner.
You can try this FOUR + 1 settings for NSPopUpbutton:
In my example, "allPersons" is equivalent to your "Authors".
I have allPersons available as a property (NSArray*) in File's owner.
Additionally, I bound the tableView delegate to File's owner. If this is not bound, I just get a default list :Item1, Item2, Item3
I always prefer the programmatic approach. Create a category on NSTableCellView:
+(instancetype)tableCellPopUpButton:(NSPopUpButton **)popUpButton
identifier:(NSString *)identifier
arrayController:(id)arrayController
relationship:(NSString *)relationshipName
relationshipArrayController:(NSArrayController *)relationshipArrayController
relationshipAttribute:(NSString *)relationshipAttribute
relationshipAttributeIsScalar:(BOOL)relationshipAttributeIsScalar
valueTransformers:(NSDictionary *)valueTransformers
{
NSTableCellView *newInstance = [[self alloc] init];
newInstance.identifier = identifier;
NSPopUpButton *aPopUpButton = [[NSPopUpButton alloc] init];
aPopUpButton.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[aPopUpButton bind:NSContentBinding //the collection of objects in the pop-up
toObject:relationshipArrayController
withKeyPath:#"arrangedObjects"
options:nil];
NSMutableDictionary *contentBindingOptions = [NSMutableDictionary dictionaryWithDictionary:[[TBBindingOptions class] contentBindingOptionsWithRelationshipName:relationshipName]];
NSValueTransformer *aTransformer = [valueTransformers objectForKey:NSValueTransformerNameBindingOption];
if (aTransformer) {
[contentBindingOptions setObject:aTransformer forKey:NSValueTransformerNameBindingOption];
}
[aPopUpButton bind:NSContentValuesBinding // the labels of the objects in the pop-up
toObject:relationshipArrayController
withKeyPath:[NSString stringWithFormat:#"arrangedObjects.%#", relationshipAttribute]
options:[self contentBindingOptionsWithRelationshipName:relationshipName]];
NSMutableDictionary *valueBindingOptions = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSAllowsEditingMultipleValuesSelectionBindingOption,
[NSNumber numberWithBool:YES], NSConditionallySetsEditableBindingOption,
[NSNumber numberWithBool:YES], NSCreatesSortDescriptorBindingOption,
[NSNumber numberWithBool:YES], NSRaisesForNotApplicableKeysBindingOption,
[NSNumber numberWithBool:YES], NSValidatesImmediatelyBindingOption,
nil];;
#try {
// The object that the pop-up should use as the selected item
if (relationshipAttributeIsScalar) {
[aPopUpButton bind:NSSelectedValueBinding
toObject:newInstance
withKeyPath:[NSString stringWithFormat:#"objectValue.%#", relationshipName]
options:valueBindingOptions];
} else {
[aPopUpButton bind:NSSelectedObjectBinding
toObject:newInstance
withKeyPath:[NSString stringWithFormat:#"objectValue.%#", relationshipName]
options:valueBindingOptions];
}
}
#catch (NSException *exception) {
//NSLog(#"%# %# %#", [self class], NSStringFromSelector(_cmd), exception);
}
#finally {
[newInstance addSubview:aPopUpButton];
if (popUpButton != NULL) *popUpButton = aPopUpButton;
}
return newInstance;
}
+ (NSDictionary *)contentBindingOptionsWithRelationshipName:(NSString *)relationshipNameOrEmptyString
{
NSString *nullPlaceholder;
if([relationshipNameOrEmptyString isEqualToString:#""])
nullPlaceholder = NSLocalizedString(#"(No value)", nil);
else {
NSString *formattedPlaceholder = [NSString stringWithFormat:#"(No %#)", relationshipNameOrEmptyString];
nullPlaceholder = NSLocalizedString(formattedPlaceholder,
nil);
}
return [NSDictionary dictionaryWithObjectsAndKeys:
nullPlaceholder, NSNullPlaceholderBindingOption,
[NSNumber numberWithBool:YES], NSInsertsNullPlaceholderBindingOption,
[NSNumber numberWithBool:YES], NSRaisesForNotApplicableKeysBindingOption,
nil];
}

copy and paste text + image from NSPasteboard

we are working on a C++ Qt applciation that copies selected text and/or images from external applications, modifies it and then paste it back. Since we are on Mac, we are doing this part with Objective-C.
We are having problems trying to get an image from the Pasteboard. It works fine for text, but we are not sure about how to handle images or combination of text+image.
Since we dont know what the user might select, we should be able to perform a generic retrieval of content of the pasteboard to modify it and putting it back in the pasteboard.
We've try this:
//we thought about retrieving some generic item from pasteboard, using NSPasteboardItem
NSArray *classes = [[NSArray alloc] initWithObjects:[NSPasteboardItem class], nil];
NSDictionary *options = [NSDictionary dictionary];
NSArray *auxArray = [[NSPasteboard generalPasteboard] readObjectsForClasses:classes options:options];
NSData *archived_data = [auxArray objectAtIndex:0];
Our solution for handling text was:
NSString *text = [[NSPasteoard generalPasteboard] stringForType:NSStringPboardType];
string text_str = string([text UTF8String]);
It didnt work, so, How can we get the user selection from the pasteboard?
We need to get the raw bytes or rtf content in order to modify it as we need, and then putting it back in the pasteboard and paste it back replacing the original user selection.
Thanks!
I think this function will help you
- (IBAction)paste:sender
{
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = [NSArray arrayWithObject:[NSImage class]];
NSDictionary *options = [NSDictionary dictionary];
BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options];
if (ok)
{
NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
NSImage *image = [objectsToPaste objectAtIndex:0];
[imageView setImage:image];
}
}

Trying to create link with NSTextField

I'm using this category (is that right?) http://www.nightproductions.net/references/dsclickableurltextfield_reference.html#setAttributedStringValue
to implement clickable textfields. I've imported the header file in my controller class and set it's attributed string value like this
NSAttributedString* str = [[NSAttributedString alloc] initWithString:#"http://www.yahoo.com"];
[url setAttributedStringValue:(NSAttributedString *)str];
[str release];
The text field is not selectable and not editable.
The text field value is set but it's not clickable and it's not a link.
Thanks in advance.
I have found another easy way to show links in NSTextField. You can use HTML. Here is a short example:
-(NSAttributedString *)stringFromHTML:(NSString *)html withFont:(NSFont *)font
{
if (!font) font = [NSFont systemFontOfSize:0.0]; // Default font
html = [NSString stringWithFormat:#"<span style=\"font-family:'%#'; font-size:%dpx;\">%#</span>", [font fontName], (int)[font pointSize], html];
NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString* string = [[NSAttributedString alloc] initWithHTML:data documentAttributes:nil];
return string;
}
Now you can call the method for text field:
// #property IBOutlet NSTextField *tf;
[tf setAllowsEditingTextAttributes: YES];
[tf setSelectable:YES];
NSString *credits = #"Visit our webpage";
[tf setAttributedStringValue:[self stringFromHTML:credits withFont:[tf font]]];

Convert characters to HTML Entities in Cocoa

I am currently trying to put together an URL where I specify some GET parameters. But I want to use japanese or other characters too in this URL.
Is there a way to convert a NSString to a string containing the HTML entities for the 'special' characters in my NSString?
I am currently using the following code, which seems to work, except for 'special characters' like chinese and japanese:
NSString* url = #"/translate_a/t?client=t&sl=auto&tl=";
url = [url stringByAppendingString:destinationLanguage];
url = [url stringByAppendingString:#"&text="];
url = [url stringByAppendingString:text];
NSURL* nsurl = [[NSURL alloc] initWithScheme:#"http" host:#"translate.google.com" path:url];
NSError* error;
NSString* returnValue = [[NSString alloc] initWithContentsOfURL:nsurl encoding:NSUTF8StringEncoding error:&error];
To properly URL encode your parameters, you need to convert each name and value to UTF-8, then URL encode each name and value separately, then join names with values using '=' and name-value pairs using '&'.
I generally find it easier to put all the parameters in an NSDictionary, then build the query string from the dictionary. Here's a category that I use for doing that:
// file NSDictionary+UrlEncoding.h
#import <Cocoa/Cocoa.h>
#interface NSDictionary (UrlEncoding)
-(NSString*) urlEncodedString;
#end
// file NSDictionary+UrlEncoding.m
#import "NSDictionary+UrlEncoding.h"
// private helper function to convert any object to its string representation
static NSString *toString(id object) {
return [NSString stringWithFormat: #"%#", object];
}
// private helper function to convert string to UTF-8 and URL encode it
static NSString *urlEncode(id object) {
NSString *string = toString(object);
return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}
#implementation NSDictionary (UrlEncoding)
-(NSString*) urlEncodedString {
NSMutableArray *parts = [NSMutableArray array];
for (id key in self) {
id value = [self objectForKey: key];
NSString *part = [NSString stringWithFormat: #"%#=%#",
urlEncode(key), urlEncode(value)];
[parts addObject: part];
}
return [parts componentsJoinedByString: #"&"];
}
#end
The method build an array of name-value pairs called parts by URL encoding each key and value, then joining them together with '='. Then the parts in the parts array are joined together with '&' characters.
So for your example:
#import "NSDictionary+UrlEncoding.h"
// ...
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
[parameters setValue: #"t" forKey: #"client"];
[parameters setValue: #"auto" forKey: #"sl"];
[parameters setValue: destinationLanguage forKey: #"tl"];
[parameters setValue: text forKey: #"text"];
NSString *urlString = [#"/translate_a/t?" stringByAppendingString: [parameters urlEncodedString]];
NSString has a method -stringByAddingPercentEscapesUsingEncoding:
Here's NSString extension you can find over internet
http://code.google.com/p/wimframework/source/browse/trunk/WimFramework/Classes/Helpers/WimAdditions.m
The decode part has some error in mapping array index to actual entity number. But since you only need encoding, it's fine to use it.
For simple URL encoding of strings, many of the solutions I have seen, while technically correct, look a lot less easy to use than I would like. So I came up with the following NSString category:
#interface NSString (MLExtensions)
- (NSString *)urlencode;
#end
NSString *_mlfilterChars = #";/?:#&=+$,";
#implementation NSString (MLExtensions)
- (NSString *)urlencode
{
return [[NSString stringWithString: (NSString *)
CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)self,
NULL,
(CFStringRef)_mlfilterChars,
kCFStringEncodingUTF8)]
stringByReplacingOccurrencesOfString: #"%20" withString: #"+"];
}
#end
I'm kind of in a hurry with some other stuff I'm working on, so I kind of cheated with the %20 => + conversion step, but it all seems to work great and I've been using it for a while now with a good number of URLs in my app.
Usage is blessfully easy:
- (NSString *)URLForSearch: (NSString *)searchFor
{
return [#"http://example.org/search?query="
stringByAppendingString: [searchFor urlencode]];
}

Resources