The NSArray declaration brings up an error because "no visible #interface for NSURL declares the selector componentsseparatedbytring".
NSURL *MyURL = [[NSBundle mainBundle]
URLForResource: #"artList" withExtension:#"txt"];
NSArray *lines = [MyURL componentsSeparatedByString:#"\n"]; // each line, adjust character for line endings
for (int i = 0; i < 10; i++) {
NSString *line;
//in lines;
NSLog(#"%#", [NSString stringWithFormat:#"line: %#", line]);
_wordDefBox.text = [NSString stringWithFormat:#"%#%#",_wordDefBox.text, lines];
}
You missed a step. Once you have the URL, you need to load the file into an NSString. Then call componentsSeparatedByString on the NSString.
NSURL *myURL = [[NSBundle mainBundle]
URLForResource: #"artList" withExtension:#"txt"];
NSError *error = nil;
// Use the appropriate encoding for your file
NSString *string = [NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
if (string) {
NSArray *lines = [string componentsSeparatedByString:#"\n"];
// and the rest
} else {
NSLog(#"Unable to load string from %#: %#", myURL, error);
}
In general when you see such an error it means class X( here NSURL) doesn't have any method named Y ( e.g. componentsseparatedbystring) or at least it doesn't have it in its interface ie it's not it's public method, it may be it's private method and available to its implementation. Always try to make sense of what the compiler is telling you. To find out more you can 'Cmmd + click' on any class and it will take you to it's interface and you can see what public methods it has. Try that on NSString and NSURL
Here specifically : NSURL doesn't have that method. It doesn't belong to NSURL, it belongs NSString.
Related
My code is like...
NSString *str=[arrInitiatives valueForKey:#"FileName"];
NSLog(#"file name ----> %#",str);
NSString *imageUrl = [NSString stringWithFormat:#"%#%#", PUBLIC_UTILITY_FORMS_URL,str];
NSLog(#"----> %#",imageUrl);
[_image_imageview setImageWithURL:[NSURL URLWithString:imageUrl] placeholderImage:[UIImage imageNamed:#"noimage.png"]];
//http://setupolice.org/brcsetu/UploadFile/Lighthouse4908.jpg
from this code,i will get this
file name ----> (
"Lighthouse4908.jpg"
)
----> http://setupolice.org/brcsetu/UploadFile/(
"Lighthouse4908.jpg"
)
I want this
----> http://setupolice.org/brcsetu/UploadFile/Lighthouse4908.jpg
Try this
NSString *str=[[arrInitiatives valueForKey:#"FileName"] objectAtIndex:0];
Regards,
Amit
When you create the str variable with code
NSString *str=[arrInitiatives valueForKey:#"FileName"];
In fact it doesn't return NSString object but NSArray object. That's why filename is inside parenthesis in log:
file name ----> (
"Lighthouse4908.jpg"
)
If you're sure that filename will always be present in the array you can try what #Amit Kalghatgi suggested in his answer.
The problem is that when this array is empty you will get an error during execution of this code. I would rather do something like this:
NSArray *filenames = [arrInitiatives valueForKey:#"FileName"];
NSString *str = nil;
if (filenames.count) {
str =[arrInitiatives valueForKey:#"FileName"];
}
NSLog(#"file name ----> %#",str);
Of course before creating imageUrl you'll have to check if str is nil or not.
I have a view controller with a tableview and each tableview cell has an editable UILabel in it. Each cell is also associated with an audio file. Whenever the label is edited, I call an NSObject subclass that handles my files to rename the audio file to whatever the label was changed to. I then return the NSURL absolute string to store in core data. My question is, if this process throws an error - such as "file path already exists", how can I get it to show a UIAlertView in my view controller and not my NSObject subclass. I'm guessing I need some type of block that returns either a NSString or an NSError. I don't have much experience with blocks and any help would be appreciated.
Method in my view controller that calls the NSObject subclass to rename the file
recording.audioURL = [self.managedDocument changeFileName:previousPath withNewComponent:textField.text];
This is the method in my NSObject subclass that renames the audio file
-(NSString*) changeFileName:(NSString*) previousPath withNewComponent:(NSString*)newComponenet
{
NSURL * oldURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
oldURL = [oldURL URLByAppendingPathComponent:[previousPath lastPathComponent]];
NSString * trimmedString = [newComponenet stringByReplacingOccurrencesOfString:#" " withString:#""];
NSURL * newURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
newURL = [newURL URLByAppendingPathComponent:trimmedString];
newURL = [newURL URLByAppendingPathExtension:#"m4a"];
NSFileManager * fileManager = [NSFileManager defaultManager];
NSError * err;
BOOL result = [fileManager moveItemAtURL:oldURL toURL:newURL error:&err];
if(!result)
{
NSLog(#"Error: %#", err);
}
return newURL.absoluteString;
}
The most straightforward approach is to follow the example of the NSFileManager method you're using. Output an NSError* pointer indirectly through a by-reference parameter and make the method's direct return value indicate success or failure:
-(NSString*) changeFileName:(NSString*) previousPath withNewComponent:(NSString*)newComponenet error:(NSError**)error
{
NSURL * oldURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
oldURL = [oldURL URLByAppendingPathComponent:[previousPath lastPathComponent]];
NSString * trimmedString = [newComponenet stringByReplacingOccurrencesOfString:#" " withString:#""];
NSURL * newURL = [self.url URLByAppendingPathComponent:#"audioFiles"];
newURL = [newURL URLByAppendingPathComponent:trimmedString];
newURL = [newURL URLByAppendingPathExtension:#"m4a"];
NSFileManager * fileManager = [NSFileManager defaultManager];
BOOL result = [fileManager moveItemAtURL:oldURL toURL:newURL error:error];
if(!result)
return nil;
return newURL.absoluteString;
}
In the caller, check the return value to determine if it failed and, if so, present the error.
my url is https://photos.googleapis.com/data/upload/resumable/media/create-session/feed/api/user/111066158452258/albumid/60281009241807
i want to extract the value of user & albumid, i had tried to extract with different methods which i found in stack overflow ,but they didn't work.
Please help me out.
Thank you for your precious time.
You can take your NSURL (or init one from the URL string), and use the method pathComponents which return an array of the words in the URL (separated from the slash /), so:
pathComponents[0] == #"photos.googleapis.com"
pathComponents[1] == #"data"
...etc.
Here the snippet of code:
NSURL *url = [NSURL urlWithString:#"https://photos.googleapis.com/data/upload/resumable/media/create-session/feed/api/user/111066158452258/albumid/60281009241807"];
NSString *user = url.pathComponents[9];
NSString *album = url.pathComponents[11];
I give you an example here, NSURL class is your friend. You can use e.g. pathComponents: to get an array of all components and then process this array as you need it:
NSURL *url = [NSURL URLWithString:#"https://photos.googleapis.com/data/upload/resumable/media/create-session/feed/api/user/111066158452258/albumid/60281009241807"];
NSArray *components = [url pathComponents];
NSLog(#"path components: %#", components);
NSLog(#"user: %#", components[9]);
NSLog(#"albumid: %#", components[11]);
NSURL *url = [NSURL URLWithString:#"https://photos.googleapis.com/data/upload/resumable/media/create-session/feed/api/user/111066158452258/albumid/60281009241807"];
NSArray *pathComponentsArray = [url pathComponents];
NSString*userValue;
NSString*albumidValue;
for(int i=0;i<[pathComponentsArray count];i++)
{
if([pathComponentsArray[i] isEqualToString:#"user"])
{
userValue = pathComponentsArray[i+1];
}
if([pathComponentsArray[i] isEqualToString:#"albumid"])
{
albumidValue = pathComponentsArray[i+1];
}
}
I am using this code to get book names from a config.plist file. However my memory management is problematic. The '[dict release]' breaks the app completely and it exits.
The code works when the '[dict release]' is removed but it causes memory leaks as far as I can tell.
bnames is a global NSMutableArray
What am I doing wrong?
- (NSString *)loadBookname: (NSInteger) bookToLoad {
bookToLoad = [self bookOrder:bookToLoad];
//---get the path to the property list file---
plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
//---if the property list file can be found---
if ([[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
//---load the content of the property list file into a NSDictionary object---
dict = [[NSDictionary alloc] initWithContentsOfFile:plistFileNameConf];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
else {
//---load the property list from the Resources folder---
NSString *pListPath = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
plistFileNameConf = nil;
NSString *bookNameTemp;
bookNameTemp = [bnames objectAtIndex:bookToLoad - 1];
NSLog(#"bookName: %#", bookNameTemp);
return bookNameTemp;
}
You need to allocate your array properly:
bnames = [[NSArray alloc] initWithArray:[dict valueForKey:#"BookNames"]];
Double check that your dict returns the right data type.
There does not appear to be anything wrong with the way you allocate NSDictionary (although you could also use the [NSDictionary dictionaryWithContentsOfFile:] and save yourself having to worry about the release.
Either way I would suggest the issue is not with the [release] but probably the line BEFORE release:
bnames = [dict valueForKey:#"BookNames"];
a) Where is that allocated. I don't see an allocation or declaration of it anywhere?
b) What type of value do you expect back?
Put a break point on it and make sure your getting what you expect or anything.
If dict is not already a strong property, make it one. Then, use self.dict when assigning to it (and keep the release).
I've found what appears to be a better solution to the issue. This lets iOS manage the memory.
//---finds the path to the application's Documents directory---
- (NSString *) documentsPath {
NSLog(#"Start documentsPath");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
// NSLog(#"Found documentsPath 40");
NSLog(#"End documentsPath");
return documentsDir;
}
- (NSString *) configPath {
NSLog(#"Start configPath");
NSString *plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
plistFileNameConf = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
}
NSLog(#"plistFile: %#",plistFileNameConf);
NSLog(#"End configPath");
return plistFileNameConf;
}
The following calls the above code as necessary:
NSString *Choice;
NSArray *properties;
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:[self configPath]];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp) {
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
Choice = [temp objectForKey:#"Choice"];
properties = [temp objectForKey:Choice];
For some crazy reason I can't find a way to get a list of files with a glob for a given directory.
I'm currently stuck with something along the lines of:
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager]
directoryContentsAtPath:bundleRoot];
..and then stripping out the stuff I don't want, which sucks. But what I'd really like is to be able to search for something like "foo*.jpg" instead of asking for the entire directory, but I've not been able to find anything like that.
So how the heck do you do it?
You can achieve this pretty easily with the help of NSPredicate, like so:
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.jpg'"];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];
If you need to do it with NSURL instead it looks like this:
NSURL *bundleRoot = [[NSBundle mainBundle] bundleURL];
NSArray * dirContents =
[fm contentsOfDirectoryAtURL:bundleRoot
includingPropertiesForKeys:#[]
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
NSPredicate * fltr = [NSPredicate predicateWithFormat:#"pathExtension='jpg'"];
NSArray * onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];
This works quite nicely for IOS, but should also work for cocoa.
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSFileManager *manager = [NSFileManager defaultManager];
NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:bundleRoot];
NSString *filename;
while ((filename = [direnum nextObject] )) {
//change the suffix to what you are looking for
if ([filename hasSuffix:#".data"]) {
// Do work here
NSLog(#"Files in resource folder: %#", filename);
}
}
What about using NSString's hasSuffix and hasPrefix methods? Something like (if you're searching for "foo*.jpg"):
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot];
for (NSString *tString in dirContents) {
if ([tString hasPrefix:#"foo"] && [tString hasSuffix:#".jpg"]) {
// do stuff
}
}
For simple, straightforward matches like that it would be simpler than using a regex library.
Very Simplest Method:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory
error:nil];
//--- Listing file by name sort
NSLog(#"\n File list %#",fileList);
//---- Sorting files by extension
NSArray *filePathsArray =
[[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory
error:nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF EndsWith '.png'"];
filePathsArray = [filePathsArray filteredArrayUsingPredicate:predicate];
NSLog(#"\n\n Sorted files by extension %#",filePathsArray);
Unix has a library that can perform file globbing operations for you. The functions and types are declared in a header called glob.h, so you'll need to #include it. If open up a terminal an open the man page for glob by typing man 3 glob you'll get all of the information you need to know to use the functions.
Below is an example of how you could populate an array the files that match a globbing pattern. When using the glob function there are a few things you need to keep in mind.
By default, the glob function looks for files in the current working directory. In order to search another directory you'll need to prepend the directory name to the globbing pattern as I've done in my example to get all of the files in /bin.
You are responsible for cleaning up the memory allocated by glob by calling globfree when you're done with the structure.
In my example I use the default options and no error callback. The man page covers all of the options in case there's something in there you want to use. If you're going to use the above code, I'd suggest adding it as a category to NSArray or something like that.
NSMutableArray* files = [NSMutableArray array];
glob_t gt;
char* pattern = "/bin/*";
if (glob(pattern, 0, NULL, >) == 0) {
int i;
for (i=0; i<gt.gl_matchc; i++) {
[files addObject: [NSString stringWithCString: gt.gl_pathv[i]]];
}
}
globfree(>);
return [NSArray arrayWithArray: files];
Edit: I've created a gist on github that contains the above code in a category called NSArray+Globbing.
You need to roll your own method to eliminate the files you don't want.
This isn't easy with the built in tools, but you could use RegExKit Lite to assist with finding the elements in the returned array you are interested in. According to the release notes this should work in both Cocoa and Cocoa-Touch applications.
Here's the demo code I wrote up in about 10 minutes. I changed the < and > to " because they weren't showing up inside the pre block, but it still works with the quotes. Maybe somebody who knows more about formatting code here on StackOverflow will correct this (Chris?).
This is a "Foundation Tool" Command Line Utility template project. If I get my git daemon up and running on my home server I'll edit this post to add the URL for the project.
#import "Foundation/Foundation.h"
#import "RegexKit/RegexKit.h"
#interface MTFileMatcher : NSObject
{
}
- (void)getFilesMatchingRegEx:(NSString*)inRegex forPath:(NSString*)inPath;
#end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
MTFileMatcher* matcher = [[[MTFileMatcher alloc] init] autorelease];
[matcher getFilesMatchingRegEx:#"^.+\\.[Jj][Pp][Ee]?[Gg]$" forPath:[#"~/Pictures" stringByExpandingTildeInPath]];
[pool drain];
return 0;
}
#implementation MTFileMatcher
- (void)getFilesMatchingRegEx:(NSString*)inRegex forPath:(NSString*)inPath;
{
NSArray* filesAtPath = [[[NSFileManager defaultManager] directoryContentsAtPath:inPath] arrayByMatchingObjectsWithRegex:inRegex];
NSEnumerator* itr = [filesAtPath objectEnumerator];
NSString* obj;
while (obj = [itr nextObject])
{
NSLog(obj);
}
}
#end
I won't pretend to be an expert on the topic, but you should have access to both the glob and wordexp function from objective-c, no?
stringWithFileSystemRepresentation doesn't appear to be available in iOS.
Swift 5
This works for cocoa
let bundleRoot = Bundle.main.bundlePath
let manager = FileManager.default
let dirEnum = manager.enumerator(atPath: bundleRoot)
while let filename = dirEnum?.nextObject() as? String {
if filename.hasSuffix(".data"){
print("Files in resource folder: \(filename)")
}
}
Swift 5 for cocoa
// Getting the Contents of a Directory in a Single Batch Operation
let bundleRoot = Bundle.main.bundlePath
let url = URL(string: bundleRoot)
let properties: [URLResourceKey] = [ URLResourceKey.localizedNameKey, URLResourceKey.creationDateKey, URLResourceKey.localizedTypeDescriptionKey]
if let src = url{
do {
let paths = try FileManager.default.contentsOfDirectory(at: src, includingPropertiesForKeys: properties, options: [])
for p in paths {
if p.hasSuffix(".data"){
print("File Path is: \(p)")
}
}
} catch { }
}