
iOSモバイルアプリにWebViewで利用規約及びプライバシーポリシーを記載する
今回はWebviewで起用規約及びプラポリにアプリからアクセスできるようにしたいと思います
1. 利用規約とプライバシーポリシーについて
利用規約とは
アプリやサービスを利用する際のルールや条件を定めた契約のことで、不正行為の防止やサービス提供者の責任範囲の明確化を目的としています。
プライバシーポリシーとは
プライバシーポリシーは、ユーザーの個人情報をどのように収集、使用、保管、共有するかを明記した方針です。特に、個人情報の取り扱いに関する法律 (例: GDPR - ヨーロッパの法律、CCPA - カリフォルニアの法律) に準拠するために必要となるそうです。
個人開発でも記載が必要か
AppleやGoogleはアプリの必須条件としてプライバシーポリシーの記載があることを必須としているようです。利用規約と合わせてプライバシーポリシーをログイン画面 (またはサービス利用開始画面)と設定画面 (ユーザーがアプリからいつでもアクセスできるようにする)で最低限表示があると安全そうです!
2. WebView遷移先のサイト/ページの作成
今回はNotionをサービスの公式サイトとして活用することにしました。
簡単にそれぞれの文章はChatGPT先生に考えてもらい、Notionでそれぞれのページを作成&内容を記載しました。

文章が書けたら、サイトとして利用したいページを表示の上、右上のShareボタンからサイトとしてPublishします

3. 設定ページからWebViewにアクセスできるようにする
こんな感じでプライバシーポリシーと利用規約のファイルをXcodeで新規作成します。編集するところは遷移先のURLのみです!
import UIKit
import WebKit
class PrivacyPolicyViewController: UIViewController {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
// Replace with your Notion link
let urlString = "https://www.notion.so/yoururl"
if let url = URL(string: urlString) {
let request = URLRequest(url: url)
webView.load(request)
}
}
}
呼び出す側の画面 (今回は設定画面)のViewControllerでは以下のように記載します
let privacypolicyVC = PrivacyPolicyViewController()
navigationController?.pushViewController(privacypolicyVC, animated: true)
うまくいくと以下のように表示されます (すごい時間に作業してるのがバレる)

4. ログイン画面からWebViewにアクセスできるようにする
こんな感じで表示されるようにします

以下サンプルコードです (ChatGPT先生にもらったもの抜粋)
import UIKit
class ViewController: UIViewController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
}
func setupUI() {
// Add Terms of Service and Privacy Policy text
let termsLabel = UILabel()
termsLabel.numberOfLines = 0
termsLabel.textAlignment = .center
termsLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(termsLabel)
// Make Terms of Service and Privacy Policy clickable
let termsText = NSMutableAttributedString(string: "By signing up, you agree to our ")
let tosAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.systemBlue,
.underlineStyle: NSUnderlineStyle.single.rawValue
]
let ppAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.systemBlue,
.underlineStyle: NSUnderlineStyle.single.rawValue
]
let tosString = NSAttributedString(string: "Terms of Service", attributes: tosAttributes)
let andString = NSAttributedString(string: " and ", attributes: nil)
let ppString = NSAttributedString(string: "Privacy Policy.", attributes: ppAttributes)
termsText.append(tosString)
termsText.append(andString)
termsText.append(ppString)
termsLabel.attributedText = termsText
termsLabel.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(termsTapped(_:)))
termsLabel.addGestureRecognizer(tapGesture)
}
@objc func termsTapped(_ sender: UITapGestureRecognizer) {
let text = (sender.view as! UILabel).text ?? ""
let termsRange = (text as NSString).range(of: "Terms of Service")
let privacyRange = (text as NSString).range(of: "Privacy Policy")
if sender.didTapAttributedTextInLabel(label: sender.view as! UILabel, inRange: termsRange) {
let tosVC = ToSViewController()
self.navigationController?.pushViewController(tosVC, animated: true)
} else if sender.didTapAttributedTextInLabel(label: sender.view as! UILabel, inRange: privacyRange) {
let privacyVC = PrivacyPolicyViewController()
self.navigationController?.pushViewController(privacyVC, animated: true)
}
}
}
private extension UITapGestureRecognizer {
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
guard let attributedText = label.attributedText else { return false }
let mutableString = NSMutableAttributedString(attributedString: attributedText)
mutableString.addAttributes([.font: label.font!], range: NSRange(location: 0, length: attributedText.length))
let layoutManager = NSLayoutManager()
let textStorage = NSTextStorage(attributedString: mutableString)
let textContainer = NSTextContainer(size: label.bounds.size)
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = label.lineBreakMode
textContainer.maximumNumberOfLines = label.numberOfLines
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
let locationOfTouchInLabel = self.location(in: label)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
let textContainerOffset = CGPoint(
x: (label.bounds.size.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
y: (label.bounds.size.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y
)
let locationOfTouchInTextContainer = CGPoint(
x: locationOfTouchInLabel.x - textContainerOffset.x,
y: locationOfTouchInLabel.y - textContainerOffset.y
)
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
return NSLocationInRange(indexOfCharacter, targetRange)
}
}