SimpleTunnel/ConnectionRuleAddEditController.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
This file contains the ConnectionRuleAddEditController class, which controls a view that is used to add or edit a Connect On Demand connection rule. |
*/ |
import UIKit |
import NetworkExtension |
// MARK: Extensions |
/// Make NEEvaluateConnectionRuleAction convertible to a string. |
extension NEEvaluateConnectionRuleAction: CustomStringConvertible { |
public var description: String { |
switch self { |
case .connectIfNeeded: return "Connect If Needed" |
case .neverConnect: return "Never Connect" |
} |
} |
} |
/// A view controller object for a view that contains input fields used to define a Evaluate Connection rule. |
class ConnectionRuleAddEditController: ConfigurationParametersViewController { |
// MARK: Properties |
/// A table cell that when tapped allows the user to select the action for the rule. |
@IBOutlet weak var actionCell: UITableViewCell! |
/// A table cell that when tapped allows the user to set the DNS Domains match condition for the rule. |
@IBOutlet weak var domainsCell: UITableViewCell! |
/// A table cell that when tapped allows the user to set the DNS Servers to be used when the rule matches. |
@IBOutlet weak var requiredDNSCell: UITableViewCell! |
/// A table cell that contains a text field where the user inputs the rule's probe URL. |
@IBOutlet weak var requiredURLProbeCell: TextFieldCell! |
/// The connection rule being edited or added. |
var targetRule = NEEvaluateConnectionRule(matchDomains: [], andAction: .connectIfNeeded) |
/// A block to execute when the user is finished editing the connection rule. |
var addRuleHandler: (NEEvaluateConnectionRule) -> Void = { rule in return } |
// MARK: UIViewController |
/// Handle the event when the view is loaded into memory. |
override func viewDidLoad() { |
super.viewDidLoad() |
cells = [ |
actionCell, |
domainsCell, |
requiredDNSCell, |
requiredURLProbeCell |
].flatMap { $0 } |
requiredURLProbeCell.valueChanged = { |
if let enteredText = self.requiredURLProbeCell.textField.text { |
self.targetRule.probeURL = URL(string: enteredText) |
} |
else { |
self.targetRule.probeURL = nil |
} |
} |
} |
/// Handle the event when the view is being displayed. |
override func viewWillAppear(_ animated: Bool) { |
super.viewWillAppear(animated) |
tableView.reloadData() |
actionCell.detailTextLabel?.text = targetRule.action.description |
domainsCell.detailTextLabel?.text = getDescriptionForStringList(targetRule.matchDomains, itemDescription: "domain", placeHolder: "Required") |
requiredDNSCell.detailTextLabel?.text = getDescriptionForStringList(targetRule.useDNSServers, itemDescription: "server") |
requiredURLProbeCell.textField.text = targetRule.probeURL?.absoluteString ?? nil |
} |
/// Set up the destination view controller for a segue away from this view controller. |
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { |
guard let identifier = segue.identifier else { return } |
switch identifier { |
case "edit-use-dns-servers": |
// The user tapped on the Use DNS Servers table cell. |
guard let stringListController = segue.destination as? StringListController else { break } |
stringListController.setTargetStrings(targetRule.useDNSServers, title: "Use DNS Servers", addTitle: "Add a server address...") { newAddresses in |
self.targetRule.useDNSServers = newAddresses |
} |
case "edit-connection-rule-action": |
// The user tapped on the Action table cell. |
guard let enumController = segue.destination as? EnumPickerController else { break } |
let enumValues: [NEEvaluateConnectionRuleAction] = [ .connectIfNeeded, .neverConnect, ], |
stringValues = enumValues.flatMap { $0.description }, |
currentSelection = enumValues.index { $0 == targetRule.action } |
enumController.setValues(stringValues, title: "Action", currentSelection: currentSelection) { newRow in |
let newAction = enumValues[newRow] |
guard self.targetRule.action != newAction else { return } |
let newRule = NEEvaluateConnectionRule(matchDomains: self.targetRule.matchDomains, andAction: newAction) |
newRule.useDNSServers = self.targetRule.useDNSServers |
newRule.probeURL = self.targetRule.probeURL |
self.targetRule = newRule |
} |
case "edit-connection-rule-match-domains": |
// The user tapped on the Match Domains table cell. |
guard let stringListController = segue.destination as? StringListController else { break } |
stringListController.setTargetStrings(targetRule.matchDomains, title: "Match Domains", addTitle: "Add a domain...") { newStrings in |
let newRule = NEEvaluateConnectionRule(matchDomains: newStrings, andAction: self.targetRule.action) |
newRule.useDNSServers = self.targetRule.useDNSServers |
newRule.probeURL = self.targetRule.probeURL |
self.targetRule = newRule |
} |
default: |
break |
} |
} |
// MARK: Interface |
/// Set the target connection rule, the title of the view, and the block to execute when the user if finished editing the rule. |
func setTargetRule(_ rule: NEEvaluateConnectionRule?, title: String, saveHandler: @escaping (NEEvaluateConnectionRule) -> Void) { |
if let newRule = rule { |
targetRule = newRule |
} else { |
targetRule = NEEvaluateConnectionRule(matchDomains: [], andAction: .connectIfNeeded) |
} |
navigationItem.title = title |
addRuleHandler = saveHandler |
} |
/// Handle the user tapping on the "Done" button. |
@IBAction func saveTargetRule(_ sender: AnyObject) { |
addRuleHandler(targetRule) |
performSegue(withIdentifier: "save-connection-rule", sender: sender) |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-10-04