Get Current URL (UIWebView) - objective-c

Simply enough, I need to know how to obtain the current URL that the UIWebView is in. That way, I would be able to add such features as bookmarking, sharing, etc.
The crux of the question is, what can I do to obtain the current URL of the webvew?
EDIT: Solution:
NSString *currentURL = myWebView.request.URL.absoluteString;

NSString *currentURL = myWebView.request.URL.absoluteString;

[[[web request] URL] absoluteString]
Will give you the current url as a String.

In Swift if you need to get your URL you need to write this block of code:
func webViewDidFinishLoad(webView: UIWebView) {
let currentURL = webView.request?.mainDocumentURL
print(currentURL)
}

Related

OS X - WebView questions

I am using webview in one of OS X app and got strange requirement from client that:
1) Need to show address bar in app for webview, I tried if there's any support by webview but couldn't really find. I know I can do that by having a text field and show URL in that but I am not sure if that's the right way so is there any other better way, please suggest.
2) Need to also check whether loaded URL has SSL support and show some icon like padlock (open/close). So again is there any support or feature of Webview that i can use or I just have to check for URL prefix of http or https? Please help.
Thanks in advance.
MP
That is exactly what you should do. Create the text field, and insert this bit of code into your application:
- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:#"window.location"];
[myTextField setStringValue:currentURL];
}
For the second part of your question, use the currentURL string, and check if https:// exists in the string using the NSNotFound method. By using [myString rangeOfString:#"string_to_search_for"].location != NSNotFound, it will return true if the rangeOfString: is found. (!= means not equal to.) (So != NSNotFound means that your rangeOfString is not equal to not being found... if that makes sense)
- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:#"window.location"];
if ([currentURL rangeOfString:#"https://"].location != NSNotFound) {
// *https://* exists! Show your closed padlock image!
} else {
// *https://* does not exist. Show your open padlock image.
}
}
Hope this was helpful!

NSURL baseURL returns nil. Any other way to get the actual base URL

I think I don't understand the concept of "baseURL". This:
NSLog(#"BASE URL: %# %#", [NSURL URLWithString:#"http://www.google.es"], [[NSURL URLWithString:#"http://www.google.es"] baseURL]);
Prints this:
BASE URL: http://www.google.es (null)
And of course, in the Apple docs I read this:
Return Value
The base URL of the receiver. If the receiver is an absolute URL, returns nil.
I'd like to get from this example URL:
https://www.google.es/search?q=uiviewcontroller&aq=f&oq=uiviewcontroller&sourceid=chrome&ie=UTF-8
This base URL
https://www.google.es
My question is simple. Is there any cleaner way of getting the actual base URL without concatenating the scheme and the hostname? I mean, what's the purpose of base URL then?
-baseURL is a concept purely of NSURL/CFURL rather than URLs in general. If you did this:
[NSURL URLWithString:#"search?q=uiviewcontroller"
relativeToURL:[NSURL URLWithString:#"https://www.google.es/"]];
then baseURL would be https://www.google.es/. In short, baseURL is only populated if the NSURL is created using a method that explicitly passes in a base URL. The main purpose of this feature is to handle relative URL strings such as might be found in the source of a typical web page.
What you're after instead, is to take an arbitrary URL and strip it back to just the host portion. The easiest way I know to do this is a little cunning:
NSURL *aURL = [NSURL URLWithString:#"https://www.google.es/search?q=uiviewcontroller"];
NSURL *hostURL = [[NSURL URLWithString:#"/" relativeToURL:aURL] absoluteURL];
This will give a hostURL of https://www.google.es/
I have such a method published as -[NSURL ks_hostURL] as part of KSFileUtilities (scroll down the readme to find it documented)
If you want purely the host and not anything like scheme/port etc. then -[NSURL host] is your method.
Docs for BaseURL.
baseURL
Returns the base URL of the receiver.
- (NSURL *)baseURL
Return Value
The base URL of the receiver. If the receiver is an absolute URL, returns nil.
Availability
Available in iOS 2.0 and later.
Declared In
NSURL.h
Seems it only works for relative URLs.
You could possibly use ...
NSArray *pathComponents = [url pathComponents]
and then take the bits you want.
Or try...
NSString *host = [url host];
you can use host method
NSURL *url = [[NSURL alloc] initWithString:#"http://www.hello.com"];
NSLog(#"Host:%#", url.host);
result:
Host:www.hello.com
It might be just me, but when I think further about the double-URL solution, it sounds like something that could stop working between OS updates. So I decided to share yet another solution, definitely not beautiful either, but I find it more readable by the general public since it doesn't rely on any hidden specificity of the framework.
if let path = URL(string: resourceURI)?.path {
let baseURL = URL(string: resourceURI.replacingOccurrences(of: path, with: ""))
...
}
Here's a quick, easy, and safe way to fetch the base URL:
NSError *regexError = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"http://.*/" options:NSRegularExpressionCaseInsensitive error:&regexError];
if (regexError) {
NSLog(#"regexError: %#", regexError);
return nil;
}
NSTextCheckingResult *match = [regex firstMatchInString:url.absoluteString options:0 range:NSMakeRange(0, url.absoluteString.length)];
NSString *baseURL = [url.absoluteString substringWithRange:match.range];

Drag Files come across Sandbox(__CFPasteboardIssueSandboxExtensionForPath)

I processed drag operation from browser view to custom view.It work well in snow lepoard,but not in Mountain Lion with sandbox.
in browser view:
NSMutableArray* urls = [[[NSMutableArray alloc] init] autorelease];
..............put some NSUrl to urls array....................
[pasteboard writeObjects:[NSArray arrayWithArray:urls]];
in my receive custom view:
NSArray* pasteboardItems = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSString class]] options:nil];
NSArray* pasteboardItems2 = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil];
NSArray* pasteboardItems3 = [pasteboard readObjectsForClasses:[NSArray arrayWithObject:[NSImage class]] options:nil];
NSLog(#"%#",pasteboardItems);
NSLog(#"%#",pasteboardItems2);
NSLog(#"%#",pasteboardItems3);
my log is:
2012-08-09 18:33:43.886 iCollage[6885:303] __CFPasteboardIssueSandboxExtensionForPath: error for [/Users/xxxx/Library/Containers/xxxxxxxxxxxx/Data/Downloads/1343902069.jpg]
2012-08-09 18:33:44.546 iCollage[6885:303] ( "file://localhost/Users/xxx/Library/Containers/xxxxxxxx/Data/Downloads/1343902069.jpg")
2012-08-09 18:33:44.547 iCollage[6885:303] ( "file://localhost/Users/xxxxx/Library/Containers/xxxxxx/Data/Downloads/1343902069.jpg")
2012-08-09 18:33:44.547 iCollage[6885:303] ()
my question is:
1.how to fix this error __CFPasteboardIssueSandboxExtensionForPath;I refer the docs and found nothing about that.I am ensuer that i have the permission to access the file!google says, may be "startAccessingSecurityScopedResource" will help me, then i try and failed
2.why pasteboardItems2 have value?i write to pasteboard only url but not string.It disgusted me that I can get the url both from NSString type and NSUrl type! (I try drag a file from iFinder, the url will only exist in pasteboardItems but not pasteboardItems2).Anybody know why? I think the first problem will auto fixed when some one help me fix this problem.
I believe Apple answer question 1:
Important: Although you can support dragging file paths, in general,
you should avoid doing so unless you are certain that the destination
app will never be run in an app sandbox. If you use an NSString, OS X
has no way to know whether that string should be interpreted as a
path; thus, OS X does not expand the destination app’s sandbox to
allow access to the file or directory at that location. Instead, use
an NSURL, a bookmark, or a filename pasteboard type.
WRT to question 2, it looks like you have pasted URLs so reading NSURL objects would seem to be correct. However I think you should implement the dragging using the following code (also from the link above):
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
NSPasteboard *pboard = [sender draggingPasteboard];
if ( [[pboard types] containsObject:NSFilenamesPboardType] ) {
NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
int numberOfFiles = [files count];
// Perform operation using the list of files
}
return YES;
}
You need to generate security-scoped URL bookmark data on the sender side, and turn that data back into a URL on the receiver side. There's some other stuff you have to do after that when you want to actually access the URL; the documentation elaborates.
The receiving application, when running in a sandbox, will not be able to handle bare paths. This is a core part of being sandboxed; you are not allowed to use bare paths or their corresponding URLs to access files that aren't in your sandbox container and haven't been explicitly handed to you by the user.
Your pasteboardItems read object of NSString type, but you dragged a file(with jpg extension), you should register for NSString type in your init method:
[self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeString]];
You need to have Document Types defined in your application so that the sandboxing mechanism knows your application should be opening files with those extensions. You can do this by clicking the project on the left in Xcode, and in the Info tab, under Document Types add a new document type for each extension.
You just need to fill in the name and extensions field.
Also if you want to persist your permission to access the files dragged onto your application, you can use this class to wrap up all that logic. https://github.com/leighmcculloch/AppSandboxFileAccess

Access iTunes user preferences in OSX Lion

I want to access iTunes user preferences such as playlists programmatically.
I use to do it with the following code, however since OSX Lion, I get a nil in response.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSDictionary *userPreferences = [userDefaults persistentDomainForName:#"com.apple.iApps"];
NSArray *databasePaths = [userPreferences objectForKey:#"iTunesRecentDatabasePaths"];
I've also made sure my app has all of its entitlements enabled.
Any suggestions on how I can fix this?
Long story made short: You just can not do it using a Sandboxed app. Turn off Sandboxing and you will see that it works. Why? Well, that's because of containers. A sandbox lives in its own container and so when you call [NSUserDefaults standardUserDefaults] Cocoa uses the path of your container rather than the POSIX path of ~/Library/Preferences which is where com.apple.iApps.plist resides. That sums up why you get nil. Also, there is a blurb on this here in NSUserDefaults: link
How to fix this?
It's really not to bad. First you have to do a little bit of work to get the POSIX path of your home directory. I setup a bunch of NSURL category methods. However the root path is POSIX based. Here is the code snippet to get you started.
1.
+ (NSURL *) homePOSIXURL {
struct passwd *pwUser = getpwuid(getuid());
const char *homeDir = pwUser->pw_dir;
return [NSURL fileURLWithPath:[NSString stringWithUTF8String:homeDir] isDirectory:YES]; }
When all is said and done, construct a full path to the plist. It hasn't changed for years so you can consider it sticky.
So you might get something that looks like this now:
2.
NSURL * prefURL = [[NSURL libraryPOSIXURL] URLByAppendingPathComponent:#"Preferences" isDirectory:YES];
prefURL = [prefURL URLByAppendingPathComponent:#"com.apple.iApps.plist"];
Now let's turn this plist, which is fairly small into something we can play with. Perhaps NSData? That sounds good, right?
3.
NSData * prefData = [NSData dataWithContentsOfURL:prefURL];
Ok, finally we can use this now to get an NSDictionary. Here is how I do it.
4.
NSDictionary * prefDict = [NSDictionary collectionFromPropertyList:prefData];
Yeah, yeah another Category on NSDictionary. I must have a million of them.
Because I'm in a sharing mood, here ya go:
+ (id) collectionFromPropertyList:(NSData *)pList {
if ( [pList length] > 0 )
return [NSPropertyListSerialization propertyListWithData:pList
options:NSPropertyListImmutable
format:nil error:nil];
return nil;
}
So, you think we are done? Well, almost. If you get this far, you will get a deny like so:
deny file-read-data
/Users/UserName/Library/Preferences/com.apple.iApps.plist
Are we loving our Sandboxed app?! Basically add your temporary entitlement and you should be off to the races again. Best of luck to ya!

Get EXC_BAD_ACCESS when tableview get data from URL?

My tableview is get XML data from URL,First I declare a NSMutableArray *dataArray;
and this is how I get the data in my TableviewSample.m
- (void)getDataFromURL{
NSString *theURLAsString = [NSString stringWithFormat:GetAllData];//<-EXE_BAD_ACCESS HERE
//#define stringWithFormat:GetAllData #"http://192.168.10.28/req_alldata.php"
NSURL *theURL = [NSURL URLWithString:theURLAsString];
self.dataArray = [NSMutableArray arrayWithContentsOfURL:theURL];
}
Then I just get the elements form this array to my tableview ...
But here I have to say one more thing , actually it won't crash before I add another view...
I add a bar button to go to a webView , this webView is use to load a IP Cam stream video
When I back to the tableview , It will appear EXC_BAD_ACCESS
This is odd things I cannot to solve it...because both side code are all looks normal
If I remove this webview ,no matter how I run the program ,it won't crash...
And sometimes I leave the webView I will receive memory warning :level 2
But just only one time.
or do I use a wrong way to open an ip cam stream ???
Thanks for all reply : )
OK,here is the code different I use in my webview class
This is first version I use
- (void)viewDidAppear:(BOOL)animated{
NSString *directGoToWebCam = [NSString stringWithFormat:GetAllData];
self.IPCamWebView=[[[UIWebView alloc] initWithFrame:CGRectMake(0,0,640,960)] autorelease];
[self.IPCamWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:directGoToWebCam]]];
[self.view addSubview:self.IPCamWebView];
}
Where does GetAllData come from? It looks like that isn't pointing to anything. More code, the exact error, and a more careful description will go a long way here.
It probably has something to do with the use of #define which does not say anything about the type of the object you are using.
If you want to define a constant string in your code the best would be to use something like this:
static NSString *GetAllData = #"192.168.10.28/req_alldata.php";
Where you need to use the string you can simply write:
NSString *GoToWebCam = [NSString stringWithString:GetAllData];