I have an app that uses Instagram Integration. The App has been in the App Store for a few months with multiple version all working fine. Suddenly, the latest version I submitted to Apple was rejected because apple doesn't like the fact that Safari is launched for a User to Login to Instagram. As per their words, they care about the user experience.
The problem is I need to request an Access Token and that is how I know it has to be done. Since my App was rejected, I can't be the only one who may have faced this so I thought I should ask. Does any one know of some other method perhaps I don't know of whereby you can authenticate a users Instagram and get the required Access Token, without Launching Safari?
EDIT #1: The only other option I can think of is to use a UIWebView within my app to open the Instagram authentication process. I tried this and it just seems to be mad slow and the callback process to my app doesn't seem to initiate. So I don't know if I'm doing something wrong.
EDIT #2: Doing more research as to why the Instagram login is not working in my UIWebView, it seems to be something with how the UIWebView handles Cookies, apparently it does not recognize Cookies or something along those lines. I still don't know what exactly to do to fix this, so if anyone has a solution please provide.
Looks like this is something that could help you. You haven't given many infos about your app so I can't think of something outside the box, but try looking into Instagram iPhone Hooks and see if you can use them to trigger login when the user does something.
I'm sure this can be optimized a little bit, I probably do not need the for loop. But either way, I've spent almost a day on this issue and just don't want to touch it anymore since I was finally able to get this to work by doing the following before loading the UIWebView:
var req = NSURLRequest(URL: NSURL(string: urlString)!)
var cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies as! [NSHTTPCookie]
var reqCookies:[AnyObject] = []
for aCookie in cookies {
reqCookies += [aCookie]
}
var headers = NSHTTPCookie.requestHeaderFieldsWithCookies(reqCookies)
self.webView.loadRequest(req)
Related
I am using UIActivityViewController to post images to Instagram app from MY app.
Please note my app does not use Instagram API or log in to users' Instagram Account.
let sharingImage = button.backgroundImage(for: [])
let avc = UIActivityViewController(activityItems: [sharingImage as AnyObject], applicationActivities: nil)
avc.excludedActivityTypes = [.addToReadingList,.airDrop,.assignToContact,.copyToPasteboard,.openInIBooks,.postToFacebook,.postToFlickr,.postToTencentWeibo,.postToTwitter,.postToVimeo,.postToWeibo,.saveToCameraRoll,.message,.mail,.print]
if let wPPC = avc.popoverPresentationController {
wPPC.sourceView = followUsButton
}
self.present(avc, animated: true, completion: nil)
I am logged into my Instagram App with multiple accounts. Upon share from MY app, Instagram tries to post to the account 'A' which is currently logged in (inside the Instagram app). This makes sense.
However, if I now switch to the Instagram app and switch to account 'B' inside it, go back to MY app and then try to share again, it continues to try to post to Account 'A'.
The only way to fix it, is to kill MY app and start it again and then it loads the correct currently logged in account 'B'.
Is there a way to programmatically reload the correct Insta account while sharing?
This is only a workaround however might be your only choice at the moment as you see that even native Photos has the same issue so it is rather down to Apple to fix it.
In your application's Info.plist, add a boolean key UIApplicationExitsOnSuspend with the value YES. See the Information Property List Key Reference for more information.
This way the app is getting terminated when enters a background state and once you go back to it it will get reloaded. The user might not notice the difference.
Perhaps before killing the app you could add some interface state saving function in:
optional func applicationWillTerminate(_ application: UIApplication)
I don't know how your app is laid out but you could create a singleton class which could be implementing Codable and keep tracking all the app state variables which would have a save and load function. Saving would be triggered upon termination and loading when app is launching.
I hope it will help in some way.
EDIT1: Should work in iOS 13
Below this code should work and terminate your app however it is not recommended and you might face an issue when uploading to AppStore. I guess you can challenge the rejection with the Apple review team by explaining that they have a bug in the SDK and point them to the problem.
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
exit(0)
}
}
Short answer, I doubt.
UIActivityViewController doesn't give you control over the user's login status (which is why it's interesting to use). IMO, that's a bug on Apple side. So, unless there's a secret way to clear the authorisation tokens that the iOS runtime has stored within your app memory, I don't see how you could possibly achieve what you want.
Plus, if Photos app has the same behaviour, that's not a good sign...
Just in case, when you say that the problem occurs when switching accounts, do you mean
In MY app, you immediately try to post from the same ViewController?
You move to a parent View (hence destroying the old one)back , then to the same view as 1/?
Do you have the same result in both case? I am asking because when instantiating a new UIActivityViewController in a new view, the runtime might fetch the new user login profile, while if you instantiate it from the same view that was used to post from the old account, it might not do so (hence it'll use the old login)
This is iOS issue not specific to your app.
I am using 2 ViewControllers with 2 WKWebViews.
The WebViews use a shared WKWebViewConfiguration.
extension WKWebViewConfiguration {
static var Shared : WKWebViewConfiguration{
if sharedConfiguration == nil{
sharedConfiguration = WKWebViewConfiguration()
sharedConfiguration.websiteDataStore = WKWebsiteDataStore.default()
sharedConfiguration.processPool = WKProcessPool()
}
return sharedConfiguration
}
private static var sharedConfiguration : WKWebViewConfiguration!
}
I am passing this on each webView and from what I read this should be the solution for shared Cookies.
But because I am doing a login though the webContent I want to have the webViews SYNCHED if the user is logged in or not.
The problem happens when the user logs in. The steps that I follow are the :
1) I have identify the host and the path, and checking the navigationAction.request.url.host and navigationAction.request.url.path
when the user makes a request, and the request happens ONLY if the credentials are correct (So I know the correct host and path) I create a bool var that indicates that the users has logged in
2) After the WebView didFinish : FINISH , I call a func that reloads the webViews that have to get refreshed but the WebViews are not acting like they have the cookies.
3) after some seconds(different everytime) ,adding manual the code .reload() the web views in each preview , the webViews are synched.
I am working on iOS 9 since these are the requirements.
It looks that the cookies are asynced, and eventually they arrive to the shared processPool or websiteDataStore from my understanding.
Anyone have a solid solution?
You don't need to share same web configuration, you just need to share processPool and KWebsiteDataStore.default() after creating each webview configuration. To verify you can check cookies from Safari developer tool.
As #PS mentioned no workaround is working for him to sync cookies. I also encounter the same problem. but I tried some unexpected things to fix this issue and that is work 100%
Cookie sync takes some time to sync with cookie store for wkwebview. so my fix is just made dummy web request that will sync cookie on app start and after that, wherever you have to use your sign In or Sign Out call you can use without making any further modification.
I implemented Universal Links in our iOS 9 app and they work by calling a method in AppDelegate.swift, in which I get an NSUserActvity with an URL attached to it.
Is there a way to get the (HTTP-) referer? I need to know on which website the user has tapped the link that opened the app.
You should be able to use NSUserActivity > referrerURL instance property. See https://developer.apple.com/documentation/foundation/nsuseractivity/2875762-referrerurl.
No, there is no way to get the referrer.
An Apple employee made that pretty clear on the developer forums: https://forums.developer.apple.com/thread/65423
They say that the only way to get some kind of referrer would be to append it to the URL. Maybe take a look Google's campaign tracking URLs (utm_...).
I found another interesting solution if you need to support iOS 9 and 10 - https://appmetrica.yandex.com/blog/referrer-based-tracking-dlya-ios-tochnaya-atributsiya-dlya-lyubogo-istochnika-trafika.
Since iOS 11 I guess can be used NSUserActivity > referrerURL.
In short:
SFSafariViewController uses the same cookies as Safari app.
You can open invisible SFSafariViewController inside your app.
If your site contains some cookie - use Universal Link to pass it back to the app.
Though it requires to implement something like tracking link on your site.
First I just want to state that I already know this question exist. It is somewhat similar to mine. But since I don't have enough reputation I couldn't comment and ask if there was any progress on the issue.
Ok, so I'm trying to retrive the request_ids from the target_url, as per the Facebook docs. When the user taps on a request in the native Facebook iOS app, iOS switches to my app, and when I try to process the app launch url in order to parse out the request_ids, I can't even find the target_url.
The launch url should look something like:
fb00000000000000://authorize/#access_token=00000000000000&expires_in=86400&target_url= http://m.facebook.com/apps/friendsmashsample?fb_source=notification&request_ids=abc&ref=notif&app_request_type=Duser_to_user
But in my case the target_url is missing, and instead it looks like:
fb00000000000000://authorize/#access_token=0000000000000&expires_in=86400
So my question is: How do I get the target_url, so that I can parse the request_ids in order to deep link in my app?
Thanks!
To launch app page in App Store app on iOS 7, this URL format is required:
#"itms-apps://itunes.apple.com/app/id%#"
Can you also append the affiliate ID and campaign token to this URL like this?
#"itms-apps://itunes.apple.com/app/id%#&at=%#&ct=%#"
Or does it have to be a plain
#"https://itunes.apple.com/app/%#/id%#?mt=8&uo=4"
type URL like you do in websites? Disadvantage of this URL is it opens Safari and causes redirects.
Try it and see; the link will either open or it won't, and if it does, and if you specify a custom campaign for testing, it will either show up in PHG or it won't. Let us know what happens, as I'm curious myself.
Oh, and if it doesn't, please file a bug, as that seems like a useful feature, and it should be trivial for Apple to add it if they haven't already.