Swift - Deeplink within app to launch popup viewcontroller - ios

I'm trying to launch a deeplink from within a Label in Swift, the intention is that the deeplink launches a popup view controller with some additional information, these deeplinks will not be available externally in the app.
I have followed the following youtube video to setup the new view controller, https://www.youtube.com/watch?v=FgCIRMz_3dE, but the example here is on a button click, and i would like this to be dynamic as the content is driven from a database, i was hoping to use the following (https://github.com/TTTAttributedLabel/TTTAttributedLabel) to dyanmically add deeplinks into various words within a label.
The part i'm stuck on is how to convert the following snippet of code, into a format that can be run when the deeplink is selected, my understanding is this needs to be executed within the app delegate.
let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("sbPopUpID") as! PopUpViewController
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMoveToParentViewController(self)
Can anybody help here?

please rewrite in plain english with more details, but anyway is a bit obscure why use a deep link to "show a popup view controller with some additional information".
Passing info between controllers via deep links (custom URL is the correct name..) is wrong.
iOS is not web based.
So read other stackoverflow detailed answers to get the right approach.

Related

How to fix/debug a VoiceOver bug?

What's my problem with the VO?
It gets stuck. It focuses only on the status bar (so it doesn't see the app at all) or it focuses temporarily on a header bar in the app (so I can change the focus between about 3 element in that field). Neither switching the VO off and on nor standard gestures can help a user in such a situation.
When exactly does it happen?
The app is quite big so the exact reason is hard to determine. That's why I want to know how you would debug it. But generally the app has login screens and inside screens. When the app starts and immediately goes to one of inside screens, the VO works perfectly. When the app starts and goes through login screens, the VO gets stuck after logging in.
Any code?
To change between the login screens and the inside screens I use UIApplicationDelegate
let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let vc: WantedViewController = storyboard.instantiateViewController(withIdentifier: "WantedViewControllerId") as! WantedViewController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
Maybe it's too big change for the VO. The app uses also JGProgressHUD but I think I checked quite well that it couldn't be a reason.
Any suggestions and questions are welcome!
If you are using native UIKit widgets, then accessibility should be built in and Voiceover should find the widget. If you have a custom widget, you'll need to set isAccessibilityElement.
The presented code caused the issue indeed. I advise people with a similar problem to perform sergue instead:
performSegue(withIdentifier: "SegueToWantedViewControllerId", sender: nil)
Define it in storyboard for example with Kind as Present Modally and Presentation as Full Screen to get the same result but with VoiceOver working.

iOS Google Sign In not displaying above modally-presented view controller [duplicate]

This question already has answers here:
Google Sign In Button does Nothing
(6 answers)
Closed 2 years ago.
I've been following the directions to get Google Sign On working on my iPhone app. I'm using XCode 11.5. My iOS target is iOS 12.1.
When you click the google Sign In button you've placed on a view controller, a little alert window is supposed to pop up and ask if you want to proceed to sign in with Google.
The problem is that this doesn't happen with my Google Sign In button on a view controller that I've presented modally. Instead, nothing happens when I click the button. I can't see any alert asking me do I want to Sign In with Google. My modal presentation code looks like this:
print("Not logged in found.")
if(loginVC == nil) {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
loginVC = storyBoard.instantiateViewController(withIdentifier: "LoginVC") as! LoginViewController
loginVC!.sessionTracker = sessionTracker! // some coredata stuff I use
loginVC!.loginReceptionDelegate = logsVC! // view controller underneath this one
loginVC!.modalPresentationStyle = UIModalPresentationStyle.fullScreen
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.navC!.present(self.loginVC!, animated: true, completion: nil)
}
If I put a Google Sign In button on the view controller underneath the modally-presented one, then I see the alert when I click the Sign In button.
Why doesn't it work with the modally-presented view controller?
I've verified that I can see alerts created with UIAlertController above my modally-presented view controller, so I don't think the Google pod code is even attempting to proceed with the sign in flow for the user (my top view isn't obstructing the alert I created on my own).
This used to work. I had this exact same project working with version 4.x of Google's sign in framework about a year ago, but I bought a new mac laptop and when I cloned my project to the new computer, I encountered this issue. I've upgraded to version 5.x of their sign in pod but this hasn't solved the problem.
Flagged my question as a duplicate because I finally found the answer elsewhere here on stack overflow.
Anyway, the problem was that my modally-presented view had a tap gesture recognizer that was interfering with clicks on the Google button.
tapGesture.cancelsTouchesInView = false
Fixed it.

Weird situation Crashes on Mapview in storyboard when Add child controller or Present (Sample code added)

I have view Controller in storyboard with mapview only.
class MapVC: UIViewController {
class func viewController () -> MapVC {
let storyboard = UIStoryboard(name: "Dashboard", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "MapVC") as! MapVC
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
I have simple Login screen
On Login button action I call this method
private func addChildVC (_ vc:UIViewController) {
self.removeAllChild()
self.addChild(vc)
vc.view.frame = self.view.bounds
self.view.addSubview(vc.view)
vc.didMove(toParent: self)
self.currentCenterViewController = vc
}
With
MapVC.viewController()
App Crashes on
vc.view.frame = self.view.bounds
Weird is if I am debugging like debugger attached and when I press on Login App not crashing but when Debugger not attached on launch and then I start app in simulator then attach process and when I press login button App crashes
Present view controller is also not working crashes the app
If I remove Mapview from storyboard app is working fine in both case
When I check vc.isViewLoaded is returning false
tried loadViewIfRequired()
Clean Derived Data, Clean project restart xcode.
Verify that I have added correct Identifers
I am not able to understand the reason Please help
EDIT
Sample App
https://drive.google.com/open?id=1-otaZhhhDEH4p29CgQP7xZSX9tizceq8
Steps to reproduce
1) Run in any simulator of ios 12
2) Press stop from xcode
3) From simulator launch the app
4) Press button
EDIT2
issue video https://drive.google.com/file/d/1z9C3Re_oVYkRncnE22xRoef2Kv2WyzId/view
File a bug https://bugreport.apple.com/web/?problemID=46774084
I don't know what actually issue and why your app crash. But I have found solution.
Add MapKit.framework in Link Binary With Libraries will fix you issue.
I hope this will help you.
I have found the actual reason behind it.
It is because of view debugger framework
Here is reply from apple developer team
Engineering has provided the following information regarding this issue:
The sample project provided is not configured correctly.
The application is using the MapKit framework, but has not been configured to link with MapKit. When run using the debugger, MapKit is pulled in because it’s linked by the view debugger framework.
When the app is launched from the simulator, without the view debugger, MapKit will not be loaded into the runtime as the app has not specified this as a dependency and therefor it crashes.
Updating your sample project to link MapKit solves the issue with the application crashing.

How do I preselect the service that will be chosen in a UIActivityViewController?

I am wondering how Dolly (iOS app) does this. If I select the Twitter icon in the first screenshot, the view in the second screen appears immediately.
That second screenshot is what is presented after you typically click the Twitter service from the scrollable list presented in a UIActivityViewController (below), e.g. Facebook, Mail, Messages, Twitter, etc. But, I never had to click Twitter from the below menu.
Again, the share sheet was presented immediately. I did not have to select Twitter from the built in set of options. So, I am wondering what, if anything I can do to duplicate this behavior. Possibly a few lines that I am missing below?
func handleTwitterShareButtonTapped(){
let activityVC = UIActivityViewController.init(activityItems: [ShareActivityItemStringSource(), ShareActivityItemURLSource()], applicationActivities: [])
//preselect twitter from services somehow???
navigationController?.present(activityVC, animated: true, completion: nil)
}
Or, perhaps there is some swizzling magic that I need to do. If this does involve swizzle magic, any resources that might get me going would be extremely helpful.
Thanks!!!

Xcode UI Tests Multiple Buttons Found

I'm having a problem where my UI Test says multiple buttons found when using the following code.
app.buttons["Upgrade"].tap()
So I reran my unit test and set a breakpoint right before running that line and hit the record button and clicked the button and it generated the following code.
app.children(matching: .window).element(boundBy: 0).children(matching: .other).element(boundBy: 1).buttons["Upgrade"].tap()
Of course at the top of the test I have let app = XCUIApplication().
Any idea why this would be happening?
Sometimes when running p UIApplication.shared.windows in the debugger it has 2 values in the array. I'm not sure why as I never have multiple windows. The only interactions I have with windows is setting UIApplication.shared.keyWindow?.rootViewController to different view controllers sometimes, and the following code in didFinishLaunchingWithOptions.
// Get view controllers ready
self.window = UIWindow(frame: UIScreen.main.bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController: ViewController = mainStoryboard.instantiateViewController(withIdentifier: "FirstView") as! ViewController
// Show view controller
self.window?.rootViewController = mainViewController
self.window?.makeKeyAndVisible()
That is within an if statement and within the else statement I have pretty much the same code except instead of FirstView it's SecondView.
This message appears because there is more than one button on the screen with the accessibilityIdentifier, accessibilityLabel or value, "Upgrade", so it can't work out which one to tap.
The reason that it works when you use the recorded version is because the recording tool has identified that the search needs to be narrowed down to search inside the element of type .other at index 1, in order to be sure of which "Upgrade" button to interact with.
It's not a problem with your window(s), but with the uniqueness of your buttons' identifiers, and how you're handling them in your test.
In a situation where the button is only used once on the page of your app in question, it's best to set a unique accessibilityIdentifier on the UIButton. Its value should be unique within that page of your app, so make sure you aren't using the same string anywhere else. Then you can access the button unambiguously:
// app code
let upgradeButton: UIButton!
upgradeButton.accessibilityIdentifier = "upgradeButton"
// test code
let app = XCUIApplication()
let upgradeButton = app.buttons["upgradeButton"]
upgradeButton.tap()
In the situation where there are multiple instances of the same upgrade button on screen at the same time (e.g. where the button is part of a repeated pattern on the screen, like if there are lots of products for sale), it's OK for them each to have the same accessibilityIdentifier, but you should change the way you access the element in your test, using element(boundBy:) to access items at specified indices:
// app code
let upgradeButton: UIButton!
upgradeButton.accessibilityIdentifier = "upgradeButton"
// test code
let app = XCUIApplication()
let upgradeButton = app.buttons["upgradeButton"].element(boundBy: 1) // second upgrade button
upgradeButton.tap()
In this situation, you could also take the approach of finding the correct container view, and searching for the upgrade button inside it.
// test code
let app = XCUIApplication()
let upgradeButtonContainer = app.descendants(matching: .any).containing(.button, identifier: "upgradeButton").element(boundBy: 1) // second upgrade button-containing element
let upgradeButton = upgradeButtonContainer.buttons["upgradeButton"]
upgradeButton.tap()
I faced same issue and tried multiple things to get out of it. Ultimately i found out out that the issue started happening when i updated my Xcode to 8.3.3 and simulator os to iOS 10.3.
Switched my simulator os back to iOS 10.2 and it worked perfectly.
I am seeing similar problems since updating to Xcode 8.3 where the XCUIElementQuery is returning multiple results when there should be only one. There may be a bug introduced in this build.
https://forums.developer.apple.com/thread/75546
describes the bug and the radar is here:
https://openradar.appspot.com/31498932
I've tried the posted workaround by trying to coerce my queries to return the desired object as an XCUIElementQuery and then using element(boundBy:) and it worked for me.
It's upsetting how unstable the UI Tests are.

Resources