I am searching into a UITableView using this:
titles = [NSArray arrayWithArray:[datamanager titlesForEntriesBetween:(NSInteger)[slider minSelectedValue] and:(NSInteger)[slider maxSelectedValue]containing:searchText]];
How can I encode array value with NSASCIIStringEncoding during the search process?
(Array contains "tĂȘte" for example.. and when I search "tete" nothing matches.. so I will encode array value just for my search)
I would add change the third parameter to your datamanager function:
- (NSArray*)titlesForEntriesBetween:(NSInteger)startIndex
and:(NSInteger)stopIndex
withFunction:(BOOL(^)(NSString*))block {
NSMutableArray *retVal = [NSMutableArray array];
for(NSInteger i = startIndex; i <= stopIndex; ++i) {
NSString *string = [array_ objectAtIndex:i];
if (block(string)) {
[retVal insertObject:string];
}
}
return retVal;
}
And then I would call the function like this:
titles = [datamanager titlesForEntriesBetween:(NSInteger)[slider minSelectedValue] and:(NSInteger)[slider maxSelectedValue] withFunction:^(BOOL)(NSString *str) {
NSData *data = [str dataUsingEncoding:NSASCIIStringEncoding];
NSString *simpleString = [[[NSString alloc] initWithData:data usingEncoding: NSASCIIStringEncoding] autorelease];
return [simpleString isEqualToString:str];
}]];
Note: I just typed this in, I haven't tried to compile/run this.
Related
I have an NSTextView. I paste an image into it and see it. When I get the NSTextAttachment for the NSAttributedString of the text view, it's file wrapper is nil. How do I get the image data that was pasted into the text view?
I'm using a category on NSAttributedString to get the text attachments. I would prefer not to write to disk if it's possible.
- (NSArray *)allAttachments
{
NSError *error = NULL;
NSMutableArray *theAttachments = [NSMutableArray array];
NSRange theStringRange = NSMakeRange(0, [self length]);
if (theStringRange.length > 0)
{
NSUInteger N = 0;
do
{
NSRange theEffectiveRange;
NSDictionary *theAttributes = [self attributesAtIndex:N longestEffectiveRange:&theEffectiveRange inRange:theStringRange];
NSTextAttachment *theAttachment = [theAttributes objectForKey:NSAttachmentAttributeName];
if (theAttachment != NULL){
NSLog(#"filewrapper: %#", theAttachment.fileWrapper);
[theAttachments addObject:theAttachment];
}
N = theEffectiveRange.location + theEffectiveRange.length;
}
while (N < theStringRange.length);
}
return(theAttachments);
}
Enumerate the attachments. [NSTextStorage enumerateAttribute:...]
Get the attachment's filewrapper.
Write to a URL.
[textStorage enumerateAttribute:NSAttachmentAttributeName
inRange:NSMakeRange(0, textStorage.length)
options:0
usingBlock:^(id value, NSRange range, BOOL *stop)
{
NSTextAttachment* attachment = (NSTextAttachment*)value;
NSFileWrapper* attachmentWrapper = attachment.fileWrapper;
[attachmentWrapper writeToURL:outputURL options:NSFileWrapperWritingAtomic originalContentsURL:nil error:nil];
(*stop) = YES; // stop so we only write the first attachment
}];
This sample code will only write the first attachment to outputURL.
You can get the contained NSImage from the attachment cell.
Minimalistic example:
// assuming we have a NSTextStorage* textStorage object ready to go,
// and that we know it contains an attachment at some_index
// (in real code we would probably enumerate attachments).
NSRange range;
NSDictionary* textStorageAttrDict = [textStorage attributesAtIndex:some_index
longestEffectiveRange:&range
inRange:NSMakeRange(0,textStorage.length)];
NSTextAttachment* textAttachment = [textStorageAttributesDictionary objectForKey:#"NSAttachment"];
NSTextAttachmentCell* textAttachmentCell = textAttachment.attachmentCell;
NSImage* attachmentImage = textAttachmentCell.image;
EDITING:
OS X only (AppKit version)
#EmeraldWeapon's answer is good for Objective-C, but falls down in Swift, as in Swift the attachmentCell is not an NSTextAttachmentCell, but rather an NSTextAttachmentCellProtocol? (which does not provide .image) - so you need to cast it to a concrete instance before accessing the .image:
func firstImage(textStorage: NSTextStorage) -> NSImage? {
for idx in 0 ..< textStorage.string.count {
if
let attr = textStorage.attribute(NSAttributedString.Key.attachment, at: idx, effectiveRange: nil),
let attachment = attr as? NSTextAttachment,
let cell = attachment.attachmentCell as? NSTextAttachmentCell,
let image = cell.image {
return image
}
}
return nil
}
I have written some terrible code but it works. Is there a better way to write this? _decade.x are NSButtons.
int baseDecade = 1940;
NSString *title;
int currentDecade = 0;
- (IBAction)nameDecade:(id)sender {
currentDecade = baseDecade;
title = [NSString stringWithFormat: #"%ld", (long)currentDecade];
_decade1.stringValue = title;
currentDecade = currentDecade +10;
title = [NSString stringWithFormat: #"%ld", (long)currentDecade];
_decade2.stringValue = title;
currentDecade = currentDecade +10;
title = [NSString stringWithFormat: #"%ld", (long)currentDecade];
_decade3.stringValue = title;
In iOS you can put your buttons in a single IBOutletCollection in interface builder, or in an NSArray if you create your buttons through code. With that outlet collection / array in hand, you can use a loop to reference _decadeN by their index in the collection:
#property (nonatomic, retain) IBOutletCollection(UIButton) NSArray *decadeButtons;
...
for (int i = 0 ; i != decadeButtons.count ; i++) {
UIButton * decade = decadeButtons[i];
NSString *title = [NSString stringWithFormat: #"%ld", (long)(baseDecade+10*i)];
decade.stringValue = title;
}
Edit: OSX does not support IBOutletCollections yet, so you would need to put _decadeN buttons in an array namually:
// I am using the new array literal syntax; using arrayWithObjects will work too.
NSArray *decadeButtons = #[_decade1, _decade2, _decade3];
// Use the same loop as above:
for (int i = 0 ; i != decadeButtons.count ; i++) {
UIButton * decade = decadeButtons[i];
NSString *title = [NSString stringWithFormat: #"%ld", (long)(baseDecade+10*i)];
decade.stringValue = title;
}
I used a single label and split the word "HELLO". Now I need to match the word in another function -(void)matchWords, but the probem is only the last label is getting matched. I cannot match the other label.
For instance the word "HELLO" is there and when I click 'H' the letter 'H' should be highlighted in any colour , but the problem is that only 'o' get's highlighted for any matchable letters from input...I used iTag to set the tag value for splitted lables containing unicharacters.
Here is my function:
- (IBAction)onClick1:(id)sender {
NSString *title = [(UIButton *)sender currentTitle];
for(i=0;i<vCount;i++) {
Str = [NSString stringWithFormat:#"%c",[StrName characterAtIndex:i]];
if([title isEqualToString:Str]){
MyLable1.backgroundColor = [UIColor greenColor];
}}}
Can't you just use something like:
NSString *searchWord = #"Hello"; //The word to search against
NSString *searchChar = (UIButton *)sender.title; //The character being searched
if ([searchWord rangeOfString:searchChar].location != NSNotFound) //If found, highlight label
{
MyLable1.backgroundColor = [UIColor greenColor];
}
- (IBAction)onClick1:(id)sender {
NSString *title = [(UIButton *)sender currentTitle];
for(i=0;i<vCount;i++) {
for (NSString* key in Name){
NSLog(#"Name");
UILabel *Selected = (UILabel*)[self.view viewWithTag:[key intValue]];
if ([title isEqualToString:Selected.text]) {
pStr = [NSString stringWithFormat:#"%c",[pStrName characterAtIndex:i]];
Selected.backgroundColor = [UIColor greenColor];
}
}
}
I used this and got the output running successfully.
I have the following code which I would like to use to check user answers and output a score (out of 5). I use a plist with the answers in and check the textField.text against it. What I'm struggling with is: how to get an output score as a total using this method?
- (IBAction)checkAnswers:(UITextField *)textField
{
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"7A Cells Microscopes 3" ofType:#"plist"];
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:path2];
NSString *tester = [NSString stringWithFormat:#"%i", textField.tag];
// NSDictionary *secondDict = [dictionary valueForKey:tester];
// NSString *answer = [secondDict valueForKey:#"Answer"];
// if ([textField.text isEqualToString:[[dictionary valueForKey:tester] valueForKey:#"Answer"]]) {
// NSLog(#"YAY");
// }
NSArray *allTextFields = [[NSArray alloc] initWithObjects:eyepiece, objectiveLens, focussingKnobs, stage, mirror, nil];
for (textField in allTextFields) {
int x = 0;
if ([textField.text isEqualToString:[[dictionary valueForKey:tester] valueForKey:#"Answer"]]) {
x++;
NSLog(#"%i", x);
}
}
Any help would be much appreciated!
Many thanks.
Assuming the rest of your code is good, just move int x = 0; outside the for loop. The way you have it coded x is reset to 0 on every loop... so it never counts.
Given an NSArray of NSStrings, is there a quick way to join them together into a single NSString (with a Separator)?
NSArray * stuff = /* ... */;
NSString * combinedStuff = [stuff componentsJoinedByString:#"separator"];
This is the inverse of -[NSString componentsSeparatedByString:].
-componentsJoinedByString: on NSArray should do the trick.
There's also this variant, if your original array contains Key-Value objects from which you only want to pick one property (that can be serialized as a string ):
#implementation NSArray (itertools)
-(NSMutableString *)stringByJoiningOnProperty:(NSString *)property separator:(NSString *)separator
{
NSMutableString *res = [#"" mutableCopy];
BOOL firstTime = YES;
for (NSObject *obj in self)
{
if (!firstTime) {
[res appendString:separator];
}
else{
firstTime = NO;
}
id val = [obj valueForKey:property];
if ([val isKindOfClass:[NSString class]])
{
[res appendString:val];
}
else
{
[res appendString:[val stringValue]];
}
}
return res;
}
#end