iOS/CloudKitCatalog/CloudKitCatalog/CodeSampleViewController.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
This view controller displays some descriptive text for a code sample, the input form for configuring the sample, and the button for running it. It also has all relevant event handlers. |
*/ |
import UIKit |
import CoreLocation |
class CodeSampleViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate, UITextFieldDelegate, CLLocationManagerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPickerViewDelegate, UIPickerViewDataSource { |
// Mark: - Properties |
var locationManager: CLLocationManager = CLLocationManager() |
var imagePickerController: UIImagePickerController = UIImagePickerController() |
@IBOutlet weak var pickerHeightConstraint: NSLayoutConstraint! |
@IBOutlet weak var pickerView: UIPickerView! |
@IBOutlet weak var tableView: TableView! |
@IBOutlet weak var className: UILabel! |
@IBOutlet weak var methodName: UILabel! |
@IBOutlet weak var runButton: UIBarButtonItem! |
@IBOutlet weak var codeSampleDescription: UILabel! |
var selectedCodeSample: CodeSample? |
var groupTitle: String? |
var selectedLocationCellIndex: Int? |
var selectedImageCellIndex: Int? |
var selectedSelectionCellIndex: Int? |
override func viewDidLoad() { |
super.viewDidLoad() |
if let codeSample = selectedCodeSample { |
className.text = "Class: " + codeSample.className |
methodName.text = codeSample.methodName |
codeSampleDescription.text = codeSample.description |
} |
if let groupTitle = groupTitle { |
navigationItem.title = groupTitle |
} |
navigationItem.hidesBackButton = (navigationController!.viewControllers.first?.navigationItem.hidesBackButton)! |
let border = CALayer() |
border.backgroundColor = UIColor(red: 0.91, green: 0.91, blue: 0.91, alpha: 1).CGColor |
border.frame = CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 1.0) |
tableView.layer.addSublayer(border) |
locationManager.delegate = self |
imagePickerController.sourceType = .PhotoLibrary |
imagePickerController.delegate = self |
pickerView.delegate = self |
pickerView.dataSource = self |
validateInputs() |
} |
func validateInputs() { |
var runButtonIsEnabled = true |
if let codeSample = selectedCodeSample { |
for input in codeSample.inputs { |
if !input.isValid { |
runButtonIsEnabled = false |
break |
} |
} |
} |
runButton.enabled = runButtonIsEnabled |
} |
// MARK: - Table view data source |
func numberOfSectionsInTableView(tableView: UITableView) -> Int { |
return 1 |
} |
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
if let codeSample = selectedCodeSample { |
return codeSample.inputs.filter({ !$0.isHidden }).count |
} |
return 0 |
} |
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
if let codeSample = selectedCodeSample { |
let inputs = codeSample.inputs.filter { !$0.isHidden } |
let input = inputs[indexPath.row] |
if let input = input as? TextInput, cell = tableView.dequeueReusableCellWithIdentifier("TextFieldCell", forIndexPath: indexPath) as? TextFieldTableViewCell { |
cell.textInput = input |
cell.fieldLabel.text = input.label |
cell.textField.text = input.value |
if input.type == .Email { |
cell.textField.keyboardType = .EmailAddress |
} |
cell.textField.delegate = self |
if indexPath.row == 0 { |
cell.textField.becomeFirstResponder() |
} |
return cell |
} else if let input = input as? LocationInput, cell = tableView.dequeueReusableCellWithIdentifier("LocationFieldCell", forIndexPath: indexPath) as? LocationFieldTableViewCell { |
cell.locationInput = input |
cell.fieldLabel.text = input.label |
cell.longitudeField.delegate = self |
cell.latitudeField.delegate = self |
if indexPath.row == 0 { |
cell.latitudeField.becomeFirstResponder() |
} |
cell.lookUpButton.enabled = CLLocationManager.authorizationStatus() != .Denied |
return cell |
} else if let input = input as? ImageInput, cell = tableView.dequeueReusableCellWithIdentifier("ImageFieldCell", forIndexPath: indexPath) as? ImageFieldTableViewCell { |
cell.fieldLabel.text = input.label |
cell.imageInput = input |
return cell |
} else if let input = input as? BooleanInput, cell = tableView.dequeueReusableCellWithIdentifier("BooleanFieldCell", forIndexPath: indexPath) as? BooleanFieldTableViewCell { |
cell.fieldLabel.text = input.label |
cell.booleanField.on = input.value |
cell.booleanInput = input |
return cell |
} else if let input = input as? SelectionInput, cell = tableView.dequeueReusableCellWithIdentifier("SelectionFieldCell", forIndexPath: indexPath) as? SelectionFieldTableViewCell { |
cell.fieldLabel.text = input.label |
cell.selectedItemLabel.text = input.items.count > 0 ? (input.value != nil ? input.items[input.value!].label : input.items[0].label ) : "" |
cell.selectionInput = input |
return cell |
} |
} |
let cell = tableView.dequeueReusableCellWithIdentifier("FormFieldCell", forIndexPath: indexPath) |
return cell |
} |
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { |
if let codeSample = selectedCodeSample, _ = codeSample.inputs[indexPath.row] as? ImageInput { |
return 236.0 |
} |
return tableView.rowHeight |
} |
// Mark: - UITextFieldDelegate |
func textFieldShouldReturn(textField: UITextField) -> Bool { |
textField.resignFirstResponder() |
return true |
} |
func textFieldDidEndEditing(textField: UITextField) { |
if let contentView = textField.superview { |
if let cell = contentView.superview as? TextFieldTableViewCell { |
cell.textInput.value = textField.text ?? "" |
} else if let stackView = contentView.superview, cell = stackView.superview as? LocationFieldTableViewCell, text = textField.text, value = Int(text) { |
if textField.tag == 0 { |
cell.locationInput.latitude = value |
} else if textField.tag == 1 { |
cell.locationInput.longitude = value |
} |
} |
validateInputs() |
} |
} |
func textFieldDidBeginEditing(textField: UITextField) { |
if let contentView = textField.superview, stackView = contentView.superview, cell = stackView.superview as? LocationFieldTableViewCell, errorLabel = cell.errorLabel { |
errorLabel.hidden = true |
errorLabel.layoutIfNeeded() |
} |
} |
// MARK: - UIPickerViewDataSource |
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { |
return 1 |
} |
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { |
if let selectedSelectionCellIndex = selectedSelectionCellIndex { |
let indexPath = NSIndexPath(forRow: selectedSelectionCellIndex, inSection: 0) |
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? SelectionFieldTableViewCell { |
return cell.selectionInput.items.count |
} |
} |
return 0 |
} |
// MARK: - UIPickerViewDelegate |
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { |
if let selectedSelectionCellIndex = selectedSelectionCellIndex { |
let indexPath = NSIndexPath(forRow: selectedSelectionCellIndex, inSection: 0) |
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? SelectionFieldTableViewCell { |
return cell.selectionInput.items[row].label |
} |
} |
return nil |
} |
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { |
if let selectedSelectionCellIndex = selectedSelectionCellIndex { |
let indexPath = NSIndexPath(forRow: selectedSelectionCellIndex, inSection: 0) |
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? SelectionFieldTableViewCell { |
cell.selectedItemLabel.text = cell.selectionInput.items[row].label |
UIView.animateWithDuration(0.4, animations: { |
self.pickerHeightConstraint.constant = 0 |
self.view.layoutIfNeeded() |
}) { completed in |
if completed { |
if let oldValue = cell.selectionInput.value { |
for index in cell.selectionInput.items[oldValue].toggleIndexes { |
self.selectedCodeSample!.inputs[index].isHidden = true |
} |
} |
for index in cell.selectionInput.items[row].toggleIndexes { |
self.selectedCodeSample!.inputs[index].isHidden = false |
} |
cell.selectionInput.value = row |
self.tableView.reloadData() |
} |
} |
} |
} |
} |
// Mark: - CLLocationManagerDelegate |
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) { |
if let index = selectedLocationCellIndex { |
let indexPath = NSIndexPath(forRow: index, inSection: 0) |
let cell = tableView.cellForRowAtIndexPath(indexPath) as! LocationFieldTableViewCell |
cell.lookUpButton.enabled = status != .Denied |
if status == .AuthorizedWhenInUse { |
requestLocationForCell(cell) |
} |
} |
} |
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { |
if let index = selectedLocationCellIndex { |
let indexPath = NSIndexPath(forRow: index, inSection: 0) |
let cell = tableView.cellForRowAtIndexPath(indexPath) as! LocationFieldTableViewCell |
endLocationLookupForCell(cell) |
cell.errorLabel.hidden = false |
cell.errorLabel.layoutIfNeeded() |
} |
} |
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { |
if let index = selectedLocationCellIndex { |
let indexPath = NSIndexPath(forRow: index, inSection: 0) |
let cell = tableView.cellForRowAtIndexPath(indexPath) as! LocationFieldTableViewCell |
endLocationLookupForCell(cell) |
if let location = locations.last { |
cell.setCoordinate(location.coordinate) |
validateInputs() |
} |
} |
} |
func endLocationLookupForCell(cell: LocationFieldTableViewCell) { |
cell.latitudeField.enabled = true |
cell.longitudeField.enabled = true |
cell.lookUpButton.enabled = true |
cell.spinner.stopAnimating() |
} |
func requestLocationForCell(cell: LocationFieldTableViewCell) { |
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers |
locationManager.requestLocation() |
cell.latitudeField.enabled = false |
cell.longitudeField.enabled = false |
cell.spinner.startAnimating() |
cell.spinner.layoutIfNeeded() |
} |
// MARK: - UIImagePickerControllerDelegate |
func imagePickerControllerDidCancel(picker: UIImagePickerController) { |
picker.dismissViewControllerAnimated(true, completion: nil) |
} |
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String:AnyObject]) { |
if let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage, index = selectedImageCellIndex, imageURL = getImageURL() { |
let indexPath = NSIndexPath(forRow: index, inSection: 0) |
let cell = tableView.cellForRowAtIndexPath(indexPath) as! ImageFieldTableViewCell |
let imageData = UIImageJPEGRepresentation(selectedImage, 0.8) |
imageData?.writeToURL(imageURL, atomically: true) |
cell.assetView.image = selectedImage |
cell.imageInput.value = imageURL |
} |
picker.dismissViewControllerAnimated(true, completion: nil) |
} |
func getImageURL() -> NSURL? { |
if let index = selectedImageCellIndex { |
let manager = NSFileManager.defaultManager() |
do { |
let directoyURL = try manager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true) |
let tempImageName = "ck_catalog_tmp_image_\(index)" |
return directoyURL.URLByAppendingPathComponent(tempImageName) |
} catch { |
return nil |
} |
} |
return nil |
} |
// MARK: - Actions |
@IBAction func pickImage(sender: UIButton) { |
if let contentView = sender.superview, cell = contentView.superview as? ImageFieldTableViewCell { |
selectedImageCellIndex = tableView.indexPathForCell(cell)?.row |
presentViewController(imagePickerController, animated: true, completion: nil) |
} |
} |
@IBAction func runCode(sender: UIBarButtonItem) { |
if let codeSample = selectedCodeSample { |
if let error = codeSample.error { |
let alertController = UIAlertController(title: "Invalid Parameter", message: error, preferredStyle: .Alert) |
alertController.addAction(UIAlertAction(title: "Dismiss", style: .Default, handler: nil)) |
self.presentViewController(alertController, animated: true, completion: nil) |
} else { |
self.navigationController!.performSegueWithIdentifier("ShowLoadingView", sender: codeSample) |
} |
} |
} |
@IBAction func lookUpLocation(sender: UIButton) { |
if let stackView = sender.superview, contentView = stackView.superview, cell = contentView.superview as? LocationFieldTableViewCell { |
cell.errorLabel.hidden = true |
cell.lookUpButton.enabled = false |
selectedLocationCellIndex = tableView.indexPathForCell(cell)?.row |
if CLLocationManager.authorizationStatus() == .NotDetermined { |
locationManager.requestWhenInUseAuthorization() |
} else { |
requestLocationForCell(cell) |
} |
} |
} |
@IBAction func selectOption(sender: UITapGestureRecognizer) { |
let location = sender.locationInView(tableView) |
if let indexPath = tableView.indexPathForRowAtPoint(location) { |
selectedSelectionCellIndex = indexPath.row |
pickerView.reloadComponent(0) |
UIView.animateWithDuration(0.4, animations: { |
self.pickerHeightConstraint.constant = 200 |
self.view.layoutIfNeeded() |
}) |
} |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-09-13