如何通过URL Schemes实现iOS点击链接跳转APP及密码重置控制器
Hey there! Let's break this down step by step for you—covering both the fundamentals of using URL Schemes to open your iOS app from a URL, and the specific implementation for your password reset email flow.
第一步:配置APP的URL Scheme
First, you need to register a custom URL Scheme for your app in Xcode:
- Open your project, go to the Info tab, scroll down to URL Types.
- Click the
+button to add a new entry.- For Identifier, use a unique reverse-domain string (e.g.,
com.yourcompany.yourapp). - For URL Schemes, enter a custom scheme name (e.g.,
yourapp—this is what will trigger your app when used in a URL likeyourapp://).
- For Identifier, use a unique reverse-domain string (e.g.,
第二步:处理APP内的URL跳转请求
Next, you need to handle incoming URL requests in your app. The implementation varies slightly based on iOS version:
iOS 13+ (SceneDelegate)
Add this code to your SceneDelegate.swift:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let incomingURL = URLContexts.first?.url else { return } // Verify the URL uses your custom scheme if incomingURL.scheme == "yourapp" { print("Received deep link URL: \(incomingURL)") // Here you can route to the appropriate screen (we'll expand on this for password reset) } }
iOS 12 and below (AppDelegate)
If you still support older iOS versions, add this to your AppDelegate.swift:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { if url.scheme == "yourapp" { print("Received deep link URL: \(url)") return true } return false }
第三步:测试跳转
- Open Safari on your iPhone and type
yourapp://—if your app is installed, it should open automatically. - You can also test from Xcode: Go to Product > Scheme > Edit Scheme, select Run, then under Arguments Passed On Launch, add
yourapp://testand run the app.
Note: If the app isn't installed, tapping the URL will throw an error. For a better user experience, you can pair URL Schemes with Universal Links or a fallback web page that redirects to the App Store.
This flow requires coordination between your backend (to generate the deep link) and your iOS app (to handle the link and navigate to the reset screen).
后端端实现
- When a user requests a password reset, generate a short-lived, secure reset token tied to their account.
- Create a deep link URL using your app's URL Scheme, including the token and user identifier (like their email) as query parameters. Example:
yourapp://reset-password?token=abc123xyz&email=user%40example.comMake sure to URL-encode special characters (like
@in emails) to avoid parsing issues. - Insert this URL into your password reset email as a clickable link.
iOS APP端实现
1. Parse the deep link parameters
Update the URL handling code in SceneDelegate.swift (or AppDelegate.swift) to detect the reset password route and extract parameters:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { guard let incomingURL = URLContexts.first?.url else { return } guard let urlComponents = URLComponents(url: incomingURL, resolvingAgainstBaseURL: false) else { return } // Check if the URL uses our scheme and targets the reset password flow guard urlComponents.scheme == "yourapp", urlComponents.host == "reset-password" else { return } // Extract token and email from query parameters let resetToken = urlComponents.queryItems?.first(where: { $0.name == "token" })?.value let userEmail = urlComponents.queryItems?.first(where: { $0.name == "email" })?.value guard let token = resetToken, let email = userEmail else { // Handle missing parameters (e.g., show an error alert) return } // Navigate to the password reset view controller navigateToPasswordReset(token: token, email: email, scene: scene) } // Helper method to handle navigation private func navigateToPasswordReset(token: String, email: String, scene: UIScene) { // Initialize your password reset view controller let resetVC = PasswordResetViewController() resetVC.resetToken = token resetVC.userEmail = email // Pre-fill the email for user convenience // Get the root view controller to present/push the reset screen guard let windowScene = scene as? UIWindowScene, let rootViewController = windowScene.windows.first?.rootViewController else { return } // Push to navigation controller if available, otherwise present if let navController = rootViewController as? UINavigationController { navController.pushViewController(resetVC, animated: true) } else { let navWrapper = UINavigationController(rootViewController: resetVC) rootViewController.present(navWrapper, animated: true) } }
2. Password Reset View Controller Logic
In your PasswordResetViewController, add fields for the user to enter their new password, then call your backend API to reset the password:
class PasswordResetViewController: UIViewController { var resetToken: String! var userEmail: String! // IBOutlets for new password fields @IBOutlet weak var newPasswordTextField: UITextField! @IBOutlet weak var confirmPasswordTextField: UITextField! @IBAction func resetPasswordTapped(_ sender: UIButton) { guard let newPassword = newPasswordTextField.text, !newPassword.isEmpty, let confirmPassword = confirmPasswordTextField.text, confirmPassword == newPassword else { // Show error for empty or mismatched passwords return } // Call your backend reset password API let resetURL = URL(string: "https://yourappbackend.com/api/reset-password")! var request = URLRequest(url: resetURL) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") let body: [String: Any] = [ "token": resetToken, "email": userEmail, "newPassword": newPassword ] request.httpBody = try? JSONSerialization.data(withJSONObject: body) URLSession.shared.dataTask(with: request) { [weak self] data, response, error in DispatchQueue.main.async { if let error = error { // Handle API error print("Reset failed: \(error.localizedDescription)") return } // Success: Show confirmation and navigate back to login let alert = UIAlertController(title: "Success", message: "Password reset successfully!", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in self?.dismiss(animated: true) }) self?.present(alert, animated: true) } }.resume() } }
Key Security & UX Notes
- Token Expiry: Set a short expiry time for your reset tokens (e.g., 15-30 minutes) to prevent misuse.
- HTTPS: Ensure your backend API uses HTTPS to protect the password reset request.
- Fallback: If the app isn't installed, redirect users to a web-based password reset page or the App Store. You can implement this by first sending users to a backend-hosted web page that tries to open the app via URL Scheme, then falls back if it fails.
内容的提问来源于stack exchange,提问作者Manish Kumar




