I am trying to access an XML file store in the resources directory. I am using NSURL to access this file using NSURLConnection( this file is going to be swapped out for a remote service in the future).
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
URLWithString:#"file:///XMLTest.xml"]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
response = [[NSMutableData data] retain];
} else {
NSLog(#"Could not create connection");
}
The class that starts the connection implements the NSURLConnection methods:
connection:willCacheResponse:
connection:didReceiveData:
connectionDidFinishLoading:
connectionDidFinishLoading:
Once I launch this the simulator dies, no messages are printed to the console so I am at a loss for where to look. Any ideas, or am I just doing this completely wrong?
Trying to load anything from the filesystem root is wrong, wrong, wrong. Definitely wrong on the device, and probably wrong on the simulator. The resources directory should be accessed via the NSBundle class.
For example, to get a URL for a file called "Data.txt" in the resources, use the following:
NSURL *MyURL = [[NSBundle mainBundle]
URLForResource: #"Data" withExtension:#"txt"];
If you want to get a URL from a path (say, because you created a file in NSTemporaryDirectory() and you need to get that as a URL) you can easily do so by using NSURL's fileURLWithPath method:
NSString* tempPath = NSTemporaryDirectory();
NSString* tempFile = [tempPath stringByAppendingPathComponent:fileName];
NSURL* URL = [NSURL fileURLWithPath:tempFile];
Much easier than +URLWithString: and other methods.
This would also work:
Obj-C
NSString *path = [[NSBundle mainBundle] pathForResource:#"XMLTest" ofType:#"xml"];
Swift 5
let url = Bundle.main.url(forResource: "XMLTest", withExtension: "xml")!
Hope this helps!
You can try this
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"file://localhost/Users/userName/Desktop/XMLTest.xml"]];
here assuming file is in desktop.
Swift 3:
let myFileName = "somefilename"
let myURL = Bundle.main.url(forResource: myFileName, withExtension: "png")
Related
Trying to convert a string to NSURL and this is not happening.
barcodeTextLabel.text = foundCode.barcodeString;
urlToGrab = [NSString stringWithFormat:#"%#", foundCode.barcodeString]; // foundCode.barcodeString is an NSString
urlToGrab shows the following "error invalid CFStringRef"
This is how you create an NSURL from an NSString:
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
You can use following for creating the file path to url.
NSURL *yourURL = [NSURL fileURLWithPath:#"/Users/xyz/Desktop/abc.sqlite"];
If foundCode.barcodeString is the string you want as your URL, then (like the above answer) use the NSURL class method URLWithString:(NSString *).
Your code should look like:
NSURL urlToGrab = [NSURL URLWithString:foundCode.barcodeString];
Where is your error coming into to play? The way your code is, urlToGrab is an instance of NSString. I would imagine you would get an error like you described if you tried to make an HTTP request on an NSString rather than NSURL.
Swapnali patil's answer works, but I will add an explanation.
You will get a nil if the format of NSString doesn't fit file criteria for NSURL (file:///xxx/file.ext).
My needs were with loading a JPG image via URL file path to nsdata; NSURL * u=[[NSURL alloc] initWithString:fpath] returned nil, but NSURL *yourURL = [NSURL fileURLWithPath:fpath] as in mentioned answer worked. A URL for files will be file:///users/xxx/pic.jpg format and give disk access. NSURL * u=[[NSURL alloc] initWithString:(NSString*) ] will also give nil object if nsstring is web URL but if missing http://
I want to load a html page from a file, and append a hash tag to it. Is this possible?
I have tried
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"someFile" ofType:#"html"];
NSURL *fileUrl = [NSURL fileURLWithPath:[filePath stringByAppendingFormat:#"#hashtag"]];
[self.webView loadRequest:[NSURLRequest requestWithURL:fileUrl]];
NSLog(#"fileUrl = %#, reachable? %d", fileUrl, [fileUrl checkResourceIsReachableAndReturnError:nil]);
but this tries to look for the file someFile.html%23hashtag, which can't be found. Is there a way to add the hash after the NSURL object is created?
I've also tried loading the file into a string and using loadHTMLString:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"someFile" ofType:#"html"];
NSString *fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
[self.webView loadHTMLString:fileContents baseURL:[NSURL URLWithString:#"http://someFile.html#hashtag"]];
Here the hash tag does work, but my javascript references inside the html don't work. A follow on question from this approach would be, how do I reference javascript files from html loaded in as a string in a UIWebView, ie, what is the base url?
A hack I can think of is to just put all my javascript files inline in the html and load it as a string, but I'm thinking there must be a better way!
I've not tried this but how about loading the file normally without the hashtag and implementing the UIWebViewDelegate with something like this?
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[webView stringByEvaluatingJavaScriptFromString:#"window.location.href = '#hashtag';"];
}
References:
UIView that takes you to anchor link
Programmatically scroll to an Anchor Tag
As to %23 issue, I don't think Scott Kohlert's replace solution is good.
The following solutions seems better, I just copied it from here
NSURL *baseUrl = [NSURL fileURLWithPath:stringUrl];
NSURL *fullURL = [NSURL URLWithString:#"#jumpto" relativeToURL:baseUrl];
A little bit off topic, I found the Safari on iOS 6.0, 6.1 behaves differenly than on iOS 5.1 and other desktop browsers(including Safari for OSX) regarding handle URL with anchor. For one of my particular document, whether in UIWebview or mobile Safari on iOS 6.0 or 6.1, upon the first load, the page isn't scrolled to the right position, a reload will fix it. Maybe it has something to do with the fact that part of the html is produced by javascript dynamically. Any ideas?
This is how I do it in my code. I append the hashmark to the NSString, then I turn it into an NSURL using fileURLWithPath. Then I replace all instances of %23 back into a #. Its all explained in the code below, but let me know if you have any questions.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"someFile" ofType:#"html"];
NSString *filePathWithHash = [NSString stringWithFormat:#"%##yourDesiredHashTagHere",filePath];
NSURL *theURL = [NSURL fileURLWithPath:filePathWithHash];
//NSURL turns the # into %23 when using fileURLWIthPath. So we need to change it back:
NSString *finalURLString = [[NSString stringWithFormat:#"%#",theURL] stringByReplacingOccurrencesOfString:#"%23" withString:#"#"];
//Then we need to change it back to an NSURL
NSURL *finalURL = [NSURL URLWithString:finalURLString];
//And finally we load this in the webView
[theWebView loadRequest:[NSURLRequest requestWithURL:finalURL]];
You should be able to intercept the NSURLRequest, cast it to a NSMutableURLRequest, then change the URL as follows. All this would happen in shouldStartLoadWithRequest. Make sure you set the UIWebView delegate.
- (void) viewDidLoad
{
self.webView.delegate = self;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"someFile" ofType:#"html"];
NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//Make sure the request is mutable
if(![request isKindOfClass:[NSMutableURLRequest class]])
[NSException raise:#"Need to change the request, but can't" format:#""];
NSMutableURLRequest* mutableRequest = (NSMutableURLRequest*)request;
NSString* newUrl = [NSString stringWithFormat:#"%##hashtag", [[request URL] absoluteString]];
[mutableRequest setURL:[NSURL URLWithString:newUrl]];
return YES;
}
I haven't run into any cases where the request wasn't mutable, but who knows.
Or you may want to set the hash in the original URL (like you were doing), then replace the first occurrence of %23 with # in shouldStartLoadWithRequest.
An addition to #xiang's answer. Below the swift version if you're working with local html files in your app:
let urlString = "relative/path/to/your/index.html"
let anchorString = "#your-anchor"
let baseURL:NSURL? = NSBundle.mainBundle().URLForResource(urlString, withExtension: nil, subdirectory: nil)
if let url:NSURL? = NSURL(string: anchorString, relativeToURL: baseURL) {
// Do something with your URL
}
I think you have to add the hash after you create the file URL
Does it work if you change
NSURL *fileUrl = [NSURL fileURLWithPath:[filePath stringByAppendingFormat:#"#hashtag"]];
to something like:
NSString *urlString = [[NSURL fileURLWithPath:filePath] absoluteString];
NSURL *fileUrl = [NSURL URLWithString:[urlString stringByAppendingString:#"#hashtag"]];
In Swift (with WKWebView):
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let baseURL = Bundle.main.url(forResource: "myFile", withExtension: "html") {
//Load the main page and allow access to its directory
webView.loadFileURL(baseURL, allowingReadAccessTo: baseURL.deletingLastPathComponent())
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let anchor = "#myanchor"
//Use javascript to jump to the location
webView.evaluateJavaScript("location.href = '" + anchor + "'", completionHandler: nil)
}
I am trying to send a query as part a the URL to obtain an XML file, and then trying to parse the XML file using NSXMLParser and initWithContentsOfURL. However the parser is not able to parse the file. I tested the parser with the same file, but this time the file was saved on the server (it was not being generated) and it worked just fine, so I know it is not a problem with the parser.
I have come to think that it does not parse it because I need to load the file before I try to parse it, or give the initWithContentsOfURL time to load the contents. So I tried to put those contents in a NSString and a NSData and using a sleep function as well as using a block but that did not work either.
What would be the best way to go about this problem?
Here is some of the code:
NSString *surl = [NSString stringWithFormat:#"http://lxsrv7.oru.edu/~maria_hernandez/query.xml"];
url = [NSURL URLWithString:surl];
NSString *curl = [[NSString alloc] initWithContentsOfURL:url];
NSLog(#"URL: %#", surl);
NSLog(#"URL Content: %#", curl);
SXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:receivedData];
//Other stuff we have tried:
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:surl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLResponse = nil;
NSError = nil;
receivedData = [NSURLConnection sendSynchronousRequest: theRequest returningResponse: &theResponse error: &error];
Let me know if you have more questions or if you wish to see more code.
Thanks!
have you tried setting a delegate for the NSXMLParse that implements the NSXMLParserDelegate which has events for parsing the document
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html
what is the difference between NSURLConnection and NSURL?
i mean if i am downloading a file, does it make and difference which one i use?
Rgds
for:
NSString *myUrl = #"http://www.test.com/";
NSString *returnData = [NSString stringWithContentsOfURL:[NSURL URLWithString: myUrl]];
or
NSString *myUrl = #"http://www.test.com/";
NSURLRequest *myRequest = [[NSURLRequest alloc] initWithURL: [NSURL URLWithString:myUrl] ];
NSString *returnData = [NSURLConnection sendSynchronousRequest:myRequest returningResponse: nil error: nil ];
whats the difference?
thks
The Connection
An NSURLConnection object provides support to perform the loading of a URL request.
The Request
NSURLRequest objects represent a URL load request in a manner independent of protocol and URL scheme.
E.g. requestWithURL:
Creates and returns a URL request for a specified URL with default cache policy and timeout value.
+ (id)requestWithURL:(NSURL *)theURL
The URL
The NSURL class provides a way to manipulate URLs and the resources they reference. NSURL objects understand URLs as specified in RFCs 1808, 1738, and 2732. ...
To get the contents of a URL, NSString provides stringWithContentsOfURL: and NSData provides dataWithContentsOfURL:.
References:
NSURLConnection_Class/Reference/Reference.html
NSURL_Class/Reference/Reference.html#//apple_ref/doc/c_ref/NSURL
Best thing about NSURLConnection is its asynchronous behaviour so that you dont have to wait until the url is loaded.
I am wondering if theres a way to remotely write to a plist file stored on my server. The directory the file is located has write access, but i cannot seem to push the new data. Heres my code:
NSString *accountURL = [NSString stringWithFormat:#"http://www.mywebsite.com//%#.plist",txtUsername.text];
NSURL *url = [NSURL URLWithString:accountURL];
NSMutableDictionary *account = [[NSMutableDictionary alloc] initWithContentsOfURL:url];
[account setObject:#"TEST" forKey:#"LastLogin"];
if ([account writeToURL:url atomically:NO]){
NSLog(#"saved");
}else{
NSLog(#"not saved");
}
The plist file exists because I can read from it with no problem. I just cannot write to the file.
On another note, is this even AppStore-friendly if the accounts will be stored on my server?
You need to parse this web service like this and need to implement the delegate methods of parser.
-(void)startParsingForLoginUser:(NSString*)UserName
{
NSString *urlString = [NSString stringWithFormat:#"http://www.mywebsite.com//%#.plist",UserName]];
NSURL *xmlURL = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:xmlURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]autorelease];
NSURLResponse *returnedResponse = nil;
NSError *returnedError = nil;
NSData *itemData = [NSURLConnection sendSynchronousRequest:request returningResponse:&returnedResponse error:&returnedError];
xmlParser = [[NSXMLParser alloc] initWithData:itemData];
[xmlParser setDelegate:self];
[xmlParser parse];
}
And then you would be able to write the plist file on server. Moreover, you could also use the method for parsing like POST, PUT and you can also send aSynchronousRequest to the server, that depends upon you.
Read-only is easy. As soon as you get into writing something you get into permissions for: server, application, user.
To solve your problem you need to create a web service that will authenticate the user and application, check permissions and save the file. Typically it would be a server accepting a POST or PUT from your iPhone app (similar to what browsers do for upload)