NSPredicate: how to do NOT EndsWith? - iphone

I have a list of images in the app bundle and need to display appropriate ones in app, the image has the format:
###_photo_#.jpg
###: toy id, from 1000 to 2000
#: photo id, from 1
so for example
1000_photo_1.jpg
1000_photo_2.jpg
I used to get the list of files in the bundle and use a predicate to filter out other files:
#"self ENDSWITH '.jpg' AND self BEGINSWITH '%d_photo_'", toyId
but now there are retina images which end with #2x.jpg, so this method need to be fixed, I am thinking about adding:
NOT ENDSWITH '#2x.jpg'
but is this correct? should I say:
NOT (ENDSWITH '#2x.jpg')
or:
(NOT ENDSWITH '#2x.jpg')
instead?

You can use a predicate string like this:
#"(self ENDSWITH '.jpg') AND NOT (self ENDSWITH '#2x.jpg') AND (self BEGINSWITH '%d_photo_')"

You can encapsulate a predicate in another predicate:
NSPredicate *positivePredicate = [NSPredicate ...];
NSPredicate *negativePredicate = [NSCompoundPredicate notPredicateWithSubpredicate: positivePredicate];
This allows you to preserve the existing legible format string. Note that with NSCompoundPredicate, you can also build AND and OR predicates. From these three (AND, OR, NOT), you can even derive things like XNOR and NAND predicates (though how to do so is an exercise left to the reader...)

I think a better option in iOS 4.0+ is to use NSPredicate predicateWithBlock: to define your conditions. That way you can use standard NSString functions like hasSuffix: to check for your endsWith negative case.
Checkout a good tutorial here: http://www.wannabegeek.com/?p=149
Here's a basic way you could use it.
NSInteger toyId = 10;
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject hasSuffix:#".jpg"] &&
![evaluatedObject hasSuffix:#"#2x.jpg"] &&
[evaluatedObject hasPrefix:[NSString stringWithFormat:#"%#_photo_", [NSNumber numberWithInt:toyId]]];
}];
You can then grab your array of files
[arrayOfFiles filterArrayUsingPredicate:predicate];

Try this:
NOT something ENDSWITH '#2x.jpg'

Related

Multiple string variables in a function ios

I'm really new to ios and i'm trying to write a function that recieves 4 string,
Heres what I try:
this is in my h file:
-(BOOL)validate:(NSString*)fullname:(NSString*)email: NSString username:(NSString*)password
this is in my m file:
-(BOOL)validate:(NSString*)fullname:(NSString*)email: NSString username:(NSString*)password
{
NSString *emailRegex = #"[A-Z0-9A-z._%+- ]+#[A-Za-z0-0.-]+\.[A-Za-z]{2,4}";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#",emailRegex];
return YES;
}
the errors is get are that iam using an undeclared identifier
on the emailRegex
and on the emaitTest
Basicly all i'm trying to do is declare a method that recieves 4 strings:
fullname
email
username
password
and implement it.
any help would be good.
good day.
It should be as :
-(BOOL)validateFullName:(NSString*)fullName email:(NSString*)email userName:(NSString*)username withPassword:(NSString*)password;
For Better readability :
-(BOOL)validateFullName:(NSString*)fullName
email:(NSString*)email
userName:(NSString*)username
password:(NSString*)password;
*Edit: Naming convention was not best, so renamed.

NSPredicate Filtering with special characters

I am using the code below to filter the array using the predicate.
self.aPredicateString = [self.aPredicateString stringByAppendingString:[NSString stringWithFormat:#"%# contains[cd] '%#'", self.selectedSearchParameter, self.searchString]];
NSLog(#"Predicate string %#",self.aPredicateString);
self.aPredicate = [NSPredicate predicateWithFormat:self.aPredicateString];
If user enters either \ or ' the code crashes with error.
I do not understand what the mistake is? Either special characters are not allowed in NSPredicate or should I format the predicate in different way.
I wonder, why you use all this self.aPredicateString stringByAppendingString, but I think, your predicate should look like this:
self.aPredicate = [NSPredicate predicateWithFormat:#"%# contains[cd] %#", self.selectedSearchParameter, self.searchString]];
with no '' around the %#

Returning a list of directories with NSMetadataQuery and NSPredicate

I'm trying to get a list of directories in the user's iCloud folder. I worked out how to look for special types of files (such as txt files) and it works fine:
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
_query = query;
//Search all files in the Documents directories of the application’s iCloud container directories:
[query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K ENDSWITH '.txt'", NSMetadataItemFSNameKey];
[query setPredicate:pred];
[query startQuery];
However, I'm now trying to get only directories. I've read through the docs concerning NSPredicate, but I have no clue how to go about looking for directories. I guess NSPredicate is not made for this? I can check if something is a directory like this:
BOOL isDir;
BOOL exists = [fm fileExistsAtPath:path isDirectory:&isDir];
if (exists) {
/* file exists */
if (isDir) {
/* file is a directory */
}
}
But how to apply this to a NSMetadataQuery, I have no clue. I'd be grateful for any help I can get.
EDIT:
I changed the predicate to [NSPredicate predicateWithFormat:#"%K.pathExtension = ''", NSMetadataItemFSNameKey];
I then determine when the query is finished like so:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query startQuery];
- (void)queryDidFinishGathering:(NSNotification *)notification {
NSMetadataQuery *query = [notification object];
[query disableUpdates]; // You should invoke this method before iterating over query results that could change due to live updates.
[query stopQuery]; // You would call this function to stop a query that is generating too many results to be useful but still want to access the available results.
[self loadData:query];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
_query = nil; // we're done with it
}
And finally, I do a count, but this will always give me 0 however many directories I have in the cloud (I checked this via Lion and the Mobile Documents folder; e.g. I have Documents/myTXTs etc.). This is very strange. If I do a count on the text files, it will give me 4 as I have 4 txt files. So I guess my directories are not being counted:
- (void)loadData:(NSMetadataQuery *)query {
NSLog(#"Query count %i", [query resultCount]);
...
I've tried EmptyStack's answer without luck....
I've found that NSMetadataQuery does NOT find directories, The problem is not the NSPredicate is filtering directories from the results, the problem is simply the query don't find folders. I've tried with the debugger and found that all LBItems found, are of regular files not directories. I hope Apple improves this in the future.
Maybe in MountainLion this is better since they seem to have folder support ... oops off course you didn't read this here because it's still NDA. Forget it
However there is at least one way of working-around this:
For example if your file structure is;
|_Folder
| |_file
| |_file2
|_Folder1
| |_file
|_file
and we make a query with predicate:
predicateWithFormat:#"%K LIKE '*'", NSMetadataItemFSNameKey
results will be (use NSMetadataItemURLKey to get the URL)
path/to/iCloud/Documents/Folder/file
path/to/iCloud/Documents/Folder/file2
path/to/iCloud/Documents/Folder1/file
path/to/iCloud/Documents/file
What we need to do is to filter these results by ourselves by looking at the number of components of each URL and chopping URLs as needed. Items at the first level should have numberOfComponentsOfUbiquitousContainer + 1, next level would have even one more and so on.
We need to discard repetitions too (or like in this example we will get Folder twice).
Probably not optimal but works for me,
Update:
Better use below predicate, it reduce query results when crawling sub folders.
// dirPath is an NSString path of the directory you want
// to look at. Usually, for the top level directory:
// [NSFileManager URLForUbiquityContainerIdentifier:nil].path;
predicateWithFormat:#"%K BEGINSWITH %#", NSMetadataItemPathKey, dirPath];
If you want to get only the directories use the following predicate.
predicateWithFormat:#"%K.pathExtension = ''", NSMetadataItemFSNameKey
Note that, this doesn't guarantee that you will get only the directories by using this method as there are (I've seen some) files which has no extensions. But if you are sure that all your files has extensions then you can very well use this.
If you want to get all the files regardless of their extension, just add the NOT keyword to the above predicate,
predicateWithFormat:#"NOT %K.pathExtension = ''", NSMetadataItemFSNameKey
You can do this with MDQuery - which is the 'real' code that NSMetadataquery uses.
In Terminal, type 'mdls' then drag in a folder. Then type mdfind and use the provided example only change the kMDItemContentType type tree to public.folder - you will get lots of results.
Then to do this in code, you need to follow an MDQueryRef example. The code flow is identical to the Cocoa stuff, and I find the queries much easier to create and understand. You can set cocoa callbacks to the MDQuery - so its pretty well drop in compatible with NSMetadataquery.
NSMetadataQuery has some iCloud stuff that I don't think is in MDQuery. So they are not identical, I think.
Try this:
[query setPredicate:[NSPredicate predicateWithFormat:#"%K like '*.txt'", NSMetadataItemFSNameKey]];
It works for me.

Validate URL on iPhone

I was trying to validate URL links using regex, but not all the links are being completely identified. Can you please help me out?
I want the links to follow the pattern:
http://www.abcdef.org/xyz/content.aspx?menu id=190&id=3214
Assuming you are looking for a regular expression to match urls with a specific pattern:
You can use something like this to match http://www.abcdef.org/xyz/content.aspx?menu id=190&id=3214:
http://.*?/[a-zA-z]+/content.aspx\?menu id=\d+?&id=\d+
Regex for url with port in Objective c
It works well if don't have port number.
-(BOOL) validateUrl: (NSString *) candidate {
NSString *urlRegEx = #"^(http|https|ftp)\://(([a-zA-Z0-9-.]+\.[a-zA-Z]{2,3})|([0-2]*\d*\d\.[0-2]*\d*\d\.[0-2]*\d*\d\.[0-2]*\d*\d))(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9-._\?\,\'/\+&%\$#\=~])*[^.\,)(\s]$";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", urlRegEx];
return [urlTest evaluateWithObject:candidate];
}

iPhone Objective-C Form Validation

I am an old developer but new to Objective-C and iPhone development. I am looking for the best way to do form validation for values entered. I have been googling for a while and can't find any good code, but might be using the wrong key worrds, etc... I am looking for things like catching for empty string, numeric validation, date validation, etc... where it catches this either while the user is entering data (input mask type) or on the lost focus of the control.
If you can point me to some good resources that would be great!
Thanks!
Simon.
I don't know particular resources but you could begin usin NSPredicate to validate fields with regular expressions. For example, for mail validation
BOOL result;
NSString* emailRegex = #"[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate* emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
result = [emailTest evaluateWithObject:anEmailAddress];
The emailRegex suggested by Espuz has a slight problem. The range operator "-" within the [] brackets should be escaped otherwise emails having "-" character are returned as invalid.
I am using the following regex string for pattern matching that allows "_", "-" and "." characters in the address:
NSString *emailRegex = #"[a-zA-Z0-9.\\-_]{2,32}#[a-zA-Z0-9.\\-_]{2,32}\.[A-Za-z]{2,4}";
NSPredicate *regExPredicate =
[NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
BOOL validEmail = [regExPredicate evaluateWithObject:txtField.text];