So I have an app written in swift that I would like to use deep links for. A user would click on one that in the route of the URL had different pieces of information such as the id of the post or the number of likes it has or something like that. I understand that you put this in the AppDelegate:
func application(application: UIApplication,openURL url: NSURL,sourceApplication sourceApplication: String?,annotation annotation: AnyObject?) -> Bool {
println(url.host as String!)
return true
}
And that prints everything after appname://. But how can I get url.host to my view controller to be parsed into the information I need. If the declaration of URL was outside of that function then I could use this:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let InfoFromDeepLink = appDelegate.url.host
but since it's inside of that bulky Objective-C function, I'm helpless. How do you do this? I'm completely baffled. I can't even set the function to return url.host because it doesn't allow that. That's what I would do in Javascript. If you also know Javascript maybe put it in terms that a web developer would understand because I'm pretty new to this. This has to be so simple for a Swift developer right? I feel so stupid.
I would recommend using this cocoapods package called DeepLinkKit HERE IS THE SOURCE CODE
pod "DeepLinkKit"
You can simple route and have an error handling:
// Matches the URL.
router[#"timeline"] = ^{ … }
// Does not match the URL.
router[#"/timeline"] = ^{ … }
Here is a good tutorial that shows you in depth how it works.
Apple no longer supports Deep Links. It is now called Universal Links and works a bit differently.
Source
Now that Apple no longer supports URI schemes for deep linking, developers must implement Universal Links in order to deep link properly on iOS. If you are already using URI schemes, check out our blog on transitioning to Universal Links.
From: HERE
And HERE is another article on Universal Links and what they are.
Related
I have a problem that my app crashes when it is opening a file from iCloud. If I open this file from my app with a Document Picker, everything is fine. But if I try to open from outside my app, for example from iCloud or safari download it crashes. If I open it from local storage "my iphone" it is also working. It is interesting because it was good one week ago :)
So in AppDelegate, I've implemented the following method:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {}
According to the logs the crash occurs because the file does not exist.
file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/Desktop/twic1121.pgn
This is the result if I print the URL from the parameter. I think this means that the file is there.
But if i do this: print(fm.fileExists(atPath: url.path)) then this is false.
So it is obvious that after let dataFromFile = fm.contents(atPath: url.path)
this is nil.
I have no idea what could be the problem here. So the real question here is why this is nil?
It appears that the error can be many things, all not related to the class you are applying the code (AppDelegate) nor the methods you are calling.
My guess is that the URL you are calling is not correctly built (not pointing to the correct object you are trying to point to). For many reasons.
See if one of this reasons fix your issue:
(1) The end of the URL you are calling had the suffix "pgn". If you are looking to load a picture, maybe the suffix is wrong. In that case it could have been some known and supported format like "png", "jpeg" or "jpg".
(2) The "%20"symbol at the middle of your code also lifts a flag. Does not seem to be a correct URL object of swift. Maybe the URL you are using is not represented in the correct way.
(3) com~apple~CloudDocs also lifts a flag, since it would unlikely have a "~" symbol in a URL passed. This also strongly suggests that maybe the URL you are using is not represented in the correct way.
I think your URL is not pointing to where you are trying to point to, resulting in the "does exist" method return false and the loading resulting in nil.
If all of this does not fix your issue, post more details of the code. Specially what method you are calling to build/create this URL object you are using, that points to: file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/Desktop/twic1121.pgn
Is it possible to pass data from a today extension to an app? (Even when its not currently running). I wish to pass an array of objects to the main app and instantiate a viewController based on the objects passed from the today extension. I know how to open the app from the extension just not to too sure how to send data to the app.
var arrayToBePassed: [MyDataSource]
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
var url = ""
if currentSort == .recent{
url = "ext://recent"
}else{
url = "ext://popular"
}
//HOW DO I PASS arrayToBePassed to my app?
let myAppUrl = NSURL(string: url)!
extensionContext?.openURL(myAppUrl, completionHandler: { (success) in
if (!success) {
}else{
}
})
}
There's a few routes you could go down:
• In your app, implement a URL scheme that can quite literally take that array of objects, formatted as some sort of URL parameter. e.g. myAwesomeApp://objectArray=[these, are, strings]. You'll have to parse that URL yourself which should be a bit of fun.
• Look into NSUserDefaults. You can initialise a 'shared' user defaults object that both your app and your today extension can use, see here for more info. You could then store your array in here, and access it from the app when opened.
It really depends on what you're trying to do, but from the impression I get, I feel like the first option may be the best answer. I haven't provided any code, just an outline of how I'd go about it - but hopefully that should be enough to get you off to a good start.
Sharing of data is achieved through a new concept called “App Groups”. App Groups are allowed to share some data, including files, but it is worth noting that file access needs to be marshalled to avoid concurrent writes and so forth. This can be achieved through NSFileCoordination, but CoreData and NSUserDefaults handle this out of the box.
You can find the detial Steps here
I'm attempting to deep link from a Push Notification into a part of my app. I have a messages section in my app, and I want to link right into the message VC that correlates to the Push that was sent.
This is what I have done so far, but I'm not sure if I am even on the right path. The APN comes from Parse, in JSON in what I believe is a NSDictionary.
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
if let aps = userInfo["aps"] as? NSDictionary {
if let vc = aps["vc"] as? NSDictionary {
if vc == "messages" {
if let message = aps["link"] {
}
}
}
}
}
Am I on the right path here? Any Suggestions?
Thanks!
You are able to do it the way you proposed. Like anything you are able to do it multiple ways.
Your current path means you will extract and parse the json data. From there spin up the correct view from your app delegate (or segue from the initial view).
If you decide you need an architecture where your app has multiple entry points, there are frameworks that will help you do it.
Bolts Frameworks:
https://github.com/BoltsFramework/Bolts-ObjC
Programmable web had a good article on deep linking:
http://www.programmableweb.com/news/how-to-implement-deep-linking-ios/how-to/2015/07/14
The above links provide a way to structure your app so that custom urls are able to open the app into any part. If there is only going to be one extra entry point, there is probably not much point re architecting your app.
What I want to implement is as follow:
A-app (calling app) : request the return value of a-string sent as parameter : request(a-string) -> b-string.
B-app (plug-in installed separately by me or others, it plays the role of dictionary or database ) : search a-string from database and return the result (b-string).
With successful experiences of plug-in on android and with Apple's confident rhetoric of plug-in, I thought plug-in, of course, run on iOS. After a lot of hard work, however, I finally found out:
* Note : The creation and use of loadable bundles is not supported in iOS.*
Nonetheless, not giving up, I finally made it with custom URl and pasteboard:
A-app : write a-string and false state to pasteboard & call B-app via custom URL.
B-app : viewDidLoad runs following func and thereafter exit program ; func { read pasteboard and search from database & write the result(b-string) and true state to pasteboard }
A-app : while-loop detects whether state is false or true. if true, catch b-string from pasteboard.
Anyway it works but it's too long thus almost useless. Do you have any idea for better solutions? Why doesn't Apple allow plug-in for iOS? Any responses are welcome. Thank you.
I can't answer why Apple doesn't allow plug-ins, but I can offer some advice on what you're trying to achieve.
The common pattern for sending data back to your application is to implement a callback url, so the A-app would also implement a custom URI and add that to the uri sent to B-app.
B-app would then process the uri as you have already implemented, but then instead of exiting, it simply sends the data you requested in the uri passed to it.
See http://x-callback-url.com for more details and example implementations.
I am taking an Android programming course at my University only I have been allowed by the teacher to do IOS but I have to implement the same projects. This project is to have two apps. The first app is a color picker from a previous assignment. The second app is to call the colorpicker and allow the user to choose a color and when done return it too the second app to be displayed.
I have defined a custom URL scheme in my ColorPicker which works fine. In my second app I have a changeColor button that has the following IBAction method.
- (IBAction)colorChangePressed:(UIButton *)sender {
UIApplication *test = [ UIApplication sharedApplication ];
BOOL found =
[ test openURL:[ NSURL URLWithString:#"colorPicker://" ] ];
if (found) NSLog( #"Resource was found" );
else NSLog(#"unable to locate resource" );
}
This indeed launches the color picker app and it behaves as expected. My question is, after the color has been selected how do I return to the calling app with the selected color? I will add a finished button in my colorPicker to be clicked when the user is done selecting the color and I will capture the values I need but I can't figure out how to get this data back to the calling app. Is there some protocol/delegate pattern I need to implement?
The complete code is on git hub at. https://github.com/jnels124/CS390H
Thanks in advance for any insight as to how to solve my problem.
You need to have both apps with unique schemes. Encode the scheme of app1 and use it as a part of app1->app2 URL. When app2 is finished, you'll have a app2->app1 URL, use itto open app1 and send it required information (encoded).
It is similar as if you've put a String extra to app2 Intent with the name of app1 Intent, but instead of Intent you use URL and parse it as needed.
I defined a custom scheme in the other project as stated in the first answer but I was unsure how to generate the query string in the called URL and return it to the calling application to be parsed. I had this resolved in the following post.
Syntax for passing NSArray to other application with custom URL Scheme