STUZM์ ๊ธฐํ ๋จ๊ณ์์ ์๋ PHP๋ฅผ ํตํ ์น, ์ฝํ๋ฆฐ์ ์ฌ์ฉํ ์น๋ทฐ ์๋๋ก์ด๋ ์ฑ, ์ค์ํํธ๋ฅผ ์ฌ์ฉํ ์น๋ทฐ์ฉ iOS ์ฑ ์ด๋ ๊ฒ ๋๊ธฐ๋ก ๊ธฐํ๋์๋ค. ๋์ ์ฒ์ ์ค์ํํธ๋ฅผ ์จ์ ๋ค์ดํฐ๋ธ ์ฑ์ ๊ตฌํํ๋ ค ํ์ผ๋, ์ด๋ณด์ธ ๋งํผ ์๋ฃ๋ฅผ ์ฐพ๊ธฐ ์ด๋ ค์ ์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ์ด๋ณด์์๊ฒ ๋์์ด ๋๊ฒ + ๋ด๊ฐ ๋ค์ ๋ณด๊ณ ์ธ ์ ์๊ฒ ๊ธฐ๋ก์ผ๋ก ๋จ๊ธฐ๊ณ ์ ํ๋ค.
import UIKit
import WebKit
import SystemConfiguration
import Foundation
import SafariServices
// ๋คํธ์ํฌ ์ค๋ฅ class
class Reachability {
class func networkConnected() -> Bool {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) { zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return isReachable && !needsConnection
}
}
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {
@IBOutlet var myWebView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
myWebView.navigationDelegate = self
myWebView.uiDelegate = self // WKUIDelegate ์ค์ ์ถ๊ฐ
myWebViewInit()
setupWebViewConstraints()
view.backgroundColor = UIColor.white
}
// ๋คํธ์ํฌ ์ค๋ฅ
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard Reachability.networkConnected() else {
let alert = UIAlertController(title: "NetworkError", message: "๋คํธ์ํฌ๊ฐ ์ฐ๊ฒฐ๋์ด์์ง ์์ต๋๋ค.", preferredStyle: .alert)
let okAction = UIAlertAction(title: "์ข
๋ฃ", style: .default) { _ in
exit(0)
}
alert.addAction(okAction)
present(alert, animated: true, completion: nil)
return
}
}
// ์น๋ทฐ ๋ก๋
func myWebViewInit() {
// ์บ์ ์ด๊ธฐํ
WKWebsiteDataStore.default().removeData(ofTypes: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache], modifiedSince: Date(timeIntervalSince1970: 0)) {}
// ๋ค๋ก๊ฐ๊ธฐ ์ ์ค์ณ ์ค์
myWebView.allowsBackForwardNavigationGestures = true
// URL ์ค์
if let url = URL(string: "https://mobile.stuzm.com?appversion=3") {
let request = URLRequest(url: url)
myWebView.load(request)
}
}
// ์น๋ทฐ๋ฅผ safe area์ ๋ง์ถค
func setupWebViewConstraints() {
myWebView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myWebView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
myWebView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
myWebView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
myWebView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
}
// ์ธ์ฑ ๋ธ๋ผ์ฐ์ ํ์ฑํ
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else {
decisionHandler(.allow)
return
}
if let host = url.host, !host.contains("mobile.stuzm.com") {
if navigationAction.targetFrame == nil {
let safariViewController = SFSafariViewController(url: url)
present(safariViewController, animated: true, completion: nil)
decisionHandler(.cancel)
return
}
}
decisionHandler(.allow)
}
// JS ์ปจํ+alert ์ฒ๋ฆฌ
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "ํ์ธ", style: .default) { _ in
completionHandler()
}
alertController.addAction(okAction)
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
let okAction = UIAlertAction(title: "ํ์ธ", style: .default) { _ in
completionHandler(true)
}
let cancelAction = UIAlertAction(title: "์ทจ์", style: .default) { _ in
completionHandler(false)
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .alert)
alertController.addTextField { textField in
textField.text = defaultText
}
let okAction = UIAlertAction(title: "ํ์ธ", style: .default) { _ in
completionHandler(alertController.textFields?.first?.text)
}
alertController.addAction(okAction)
present(alertController, animated: true, completion: nil)
}
}
ViewController.swift ํ์ผ์ด๋ค. ์ผ๋จ ๊ธฐ๋ณธ์ ์ผ๋ก ์น๋ทฐ ๋ก๋ ๋ฐ JS Alert, Confirm์ ์ฒ๋ฆฌํ๋ ์ฝ๋, a href target='_blank'๋ฅผ ์ฒ๋ฆฌํ๋ ์ฝ๋๊ฐ ์๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก JS Alert์ Confirm๊ฐ์ ์์๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์๋์ง ์๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ถ๊ฐํด์ค์ผํ๋ค. ๋ํ a href target='_blank'๋ ๋ณดํต ์๋ก์ด ์น๋ทฐ๋ฅผ ์ฌ๋ ์์ผ๋ก ์ฒ๋ฆฌ๋ฅผ ๋ง์ด ํ๋๋ฐ, ๊ทธ๋ฐ ๋ฐฉ์์ ์ข์ํ์ง ์์์ ์ธ์ฑ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด๊ฒ ํด์คฌ๋ค.
๊ทธ๋ฆฌ๊ณ ์น๋ทฐ๋ฅผ Safe area์ ๋ง์ถฐ์ ์๋์ผ๋ก ์ฌ์ด์ฆ๋ฅผ ์กฐ์ ํด์ฃผ๋ ์ฝ๋๊ฐ ๋ค์ด๊ฐ ์๋ค. ๊ทธ๋์ ์น๋ทฐ์ ์ฌ์ด์ฆ๋ ์ค์ํ์ง ์๋ค. ๋ค๋ง, ์คํ ํ ๋์ ์์ฐ์ค๋ฌ์์ ์ํด ์์ ํฌ๋ช ์ผ๋ก ํด๋๋ ๊ฒ์ด ์ข๊ฒ ๋ค.
ํธ์ ์๋ฆผ์ ๊ตฌํํ๋ ๊ฒ์ ๊ธ๋ก ์ฐ๊ธด ๋๋ฌด ๋ณต์กํ๊ณ , ๋ ์ ๋ฐฉ๋ฒ์ ๋ฐ๋ผํด์ ์ฑ๊ณตํ์๋ค.
import UIKit
import FirebaseCore
import FirebaseMessaging
import UserNotifications
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
// Register for remote notifications
registerForRemoteNotifications(application)
// Set up Firebase Messaging delegate
Messaging.messaging().delegate = self
return true
}
// MARK: - Register for Remote Notifications
private func registerForRemoteNotifications(_ application: UIApplication) {
if #available(iOS 10.0, *) {
// For iOS 10 and later, request notification authorization
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { _, _ in }
} else {
// For iOS 9 and earlier, there is no need to register user notification settings
}
// Register for remote notifications
application.registerForRemoteNotifications()
}
}
// MARK: - UNUserNotificationCenterDelegate
// Handle presentation of notifications while the app is in the foreground
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.badge, .sound, .banner, .list])
}
// Handle user's response to a notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
print("Body: \(response.notification.request.content.body)")
print("userInfo: \(response.notification.request.content.userInfo)")
let userInfo = response.notification.request.content.userInfo
// Notification handling based on userInfo
if userInfo[AnyHashable("sesac")] as? String == "project" {
print("SESAC PROJECT")
} else {
print("NOTHING")
}
completionHandler()
}
}
// MARK: - MessagingDelegate
extension AppDelegate: MessagingDelegate {
// Handle registration token refresh
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(String(describing: fcmToken))")
if let token = fcmToken {
print("FCM Token : \(token)")
UserDefaults.standard.set(token, forKey: "fcmToken")
UserDefaults.standard.synchronize()
}
// TODO: If necessary, send the token to the application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
// Handle data messages received via FCM
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingDelegate) {
print("Received data message: \(remoteMessage.description)")
}
}
AppDelegate.swift ํ์ผ์ด๋ค. ์ ๋งํฌ์์ ์ด๋ถ๋ถ์ ๋ํ ์ค๋ช ์ด ๋๋ฌด ์๋ต๋์ด์ ์ง์ ์ฐพ์๋ค๊ฐ ์ผ๋ค(...)
์๋๋ค.