I'm stumped. Everything is working except it's not. I can call up the camera interface and take or select a photo yet UIImagePickerControllerDelegate is never being called (I've put two print statements that well, never get printed). Everything is correctly connected in IB, or so I believe it is (I'm fully ready for it so be something totally minor that I missed). Anyone care to take a frtesh set of eyes and go over this to see if I just can't see the forest for the trees?
Thanks in advance.
import UIKit
import Foundation
class afterPhotoViewController: UIViewController {
//MARK: - IBOutlet Properties
#IBOutlet weak var afterImageView: UIImageView!
#IBOutlet weak var aftervwImage: UIView!
#IBOutlet weak var cameraBtnPressed: UIButton!
//MARK: - Useful Variables
let afterImagePicker = UIImagePickerController()
var hud = HKProgressHUD()
var localTextFilePath : URL!
var isImageSetted = false
//MARK: - App Delegates
var isMain = false
var originFrame = CGRect()
override func viewDidLoad() {
super.viewDidLoad()
// Init UI Components
self.initUI()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - UI Init
func initUI() {
// Set Navigation Bar
let backButton = UIBarButtonItem(title: "", style: .plain, target: navigationController, action: nil)
navigationItem.leftBarButtonItem = backButton
self.title = "\(h_proposalNumberStr)-\(h_itemIndex)"
// Set ImageView
self.afterImageView.image = #imageLiteral(resourceName: "ic_placeholder")
self.afterImageView.clipsToBounds = false
cameraBtnPressed.layer.cornerRadius = 15
cameraBtnPressed.layer.borderColor = UIColor.lightGray.cgColor
cameraBtnPressed.layer.borderWidth = 1
self.isImageSetted = false
// self.tableView.reloadData()
}
//MARK: - UI Actions
#IBAction func cameraBtnPressed(_ sender: Any) {
//Create the AlertController and add Its action like button in Actionsheet
let actionSheetController: UIAlertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancelActionButton = UIAlertAction(title: "Cancel", style: .cancel) { _ in
}
actionSheetController.addAction(cancelActionButton)
let chooseLibraryActionButton = UIAlertAction(title: "Choose from Library", style: .default)
{ _ in
self.isMain = true
self.afterImagePicker.allowsEditing = true
self.afterImagePicker.sourceType = .photoLibrary
self.afterImagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
self.present(self.afterImagePicker, animated: true, completion: nil)
}
actionSheetController.addAction(chooseLibraryActionButton)
let takePhotoActionButton = UIAlertAction(title: "Take a Photo", style: .default)
{ _ in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
self.isMain = true
self.afterImagePicker.allowsEditing = false
self.afterImagePicker.sourceType = .camera
self.afterImagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .camera)!
self.afterImagePicker.showsCameraControls = true
self.present(self.afterImagePicker, animated: true, completion: nil)
} else {
Helper.showMessage(vc: self, title: CONSTANTS.APPINFO.APP_NAME, bodyStr: "No camera available.")
}
}
actionSheetController.addAction(takePhotoActionButton)
self.present(actionSheetController, animated: true, completion: nil)
}
//MARK: - UIImagePickerControllerDelegate
extension afterPhotoViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate {
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
print("called")
dismiss(animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("called2")
//getting actual image
var image = info[UIImagePickerControllerEditedImage] as? UIImage
if image == nil {
image = info[UIImagePickerControllerOriginalImage] as? UIImage
}
afterImageView.image = image
// Set Imageview Corner Radius
afterImageView.layer.cornerRadius = 5
afterImageView.clipsToBounds = true
self.isImageSetted = true
picker.dismiss(animated: true, completion: nil)
}
}
#raja Kishan caught my stupid simple error of forgetting to set the delegate.
Now, where's the facepalm emoji.
You have to specify that the UIImagePickerController's delegate is self, so that the events are triggered.
In your case:
afterImagePicker.delegate = self
Related
everyone!
I'm new in Swift and I've run into a problem.
I have an app that show images and I want to share some. When I click "share icon" there is default name "JPEG image". How can I change it to something like "defaultImageName".
Image I want to share
Share using default share in iOS
And here's default name that I want to change "JPEG image"
I've tried something like
imageView.image = UIImage(named: "defaultImageName")
But it's not correct, cause imageView.image it's not that I want to change.
Here's my code. I think it should be in #objc func shareTapped(), but don't really know how to do it.
import UIKit
class DetailViewController: UIViewController {
#IBOutlet var imageView: UIImageView!
var selectedImage: String?
var pictures = [String]()
override func viewDidLoad() {
super.viewDidLoad()
title = "Picture \(pictures.firstIndex(of: selectedImage!)!+1) of \(pictures.count)"
navigationItem.largeTitleDisplayMode = .never //
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareTapped))
if let imageToLoad = selectedImage {
imageView.image = UIImage(named: imageToLoad)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.hidesBarsOnTap = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.hidesBarsOnTap = false
}
#objc func shareTapped() {
guard let image = imageView.image?.jpegData(compressionQuality: 0.8) else {
print("No image found")
return
}
let vc = UIActivityViewController(activityItems: [image], applicationActivities: [])
vc.popoverPresentationController?.barButtonItem = navigationItem.rightBarButtonItem
present(vc, animated: true)
}
}
I have 3 UITextFields in my app and I need a user to fill in before he/she can see the UIButton which will calculate the result. I have tried a lot of different methods to resolve the issue but they don't seem to work and I can't quite understand some of them. I am sure there is a simple way to do that. P.S.: I don't use a storyboard
I have already tried to include UITextFieldDelegate, then writing a function, also used other ways, etc...
import UIKit
let Label: UILabel = {
let f = UILabel()
f.text = "Label"
return f
}()
let textFiled1: UITextField = {
let fw = UITextField()
fw.keyboardType = UIKeyboardType.decimalPad
return fw
}()
let textField2: UITextField = {
let fh = UITextField()
fh.keyboardType = UIKeyboardType.decimalPad
return fh
}()
let textField3: UITextField = {
let fa = UITextField()
fa.keyboardType = UIKeyboardType.numberPad
return fa
}()
class ViewController: UIViewController {
let calculateButton: UIButton = {
let c = UIButton()
c.setTitle("Calculate", for: .normal)
return c
}()
override func viewDidLoad() {
super.viewDidLoad()
setupLabel()
setupTextFieldComponents()
setupCalculateButton()
}
fileprivate func setupLabel() {
view.addSubview(fLabel)
}
fileprivate func setupTextFieldComponents() {
setupTextField1()
setupTextField2()
setupTexrField3()
}
fileprivate func setupTextField1() {
view.addSubview(textField1)
}
fileprivate func setupTextField2() {
view.addSubview(textField2)
}
fileprivate func setupTextField3() {
view.addSubview(textField3)
}
fileprivate func setupCalculateButton() {
view.addSubview(calculateButton)
}
#objc func calculateButtonPressed(sender: UIButton){
let textfield1 = Float(textField1.text!)
let textfield2 = Float(textField2.text!)
let textfield3 = Float(textField3.text!)
femaleMetaLabel.text = String(111 + (1.1 * textfield1!) + (1.1 * textfield2!) - (1.1 * textfield3!))
}
}
User is supposed to enter numeric data in all three text fields in order to calculate the result. Is there a way to make an ERROR message pop out without an app crashing?
When I am doing validation on text input that enables a button, I usually do something like this:
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var submitButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
submitButton.isEnabled = false
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self,
selector: #selector(validateInput(_:)),
name: UITextField.textDidChangeNotification,
object: usernameField)
NotificationCenter.default.addObserver(self,
selector: #selector(validateInput(_:)),
name: UITextField.textDidChangeNotification,
object: passwordField)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
#objc func validateInput(_ sender: Any?) {
submitButton.isEnabled = false
if let username = usernameField.text,
let password = passwordField.text {
// your validation rules will be more complex than this :D
if username.count > 0 && password.count > 0 {
submitButton.isEnabled = true
}
}
}
If what you need to do is pop an alert when the inputs are incorrect, simply substitute a call to a method like the one below, where you vaildate the user's input.
func showAlert() {
let alert = UIAlertController(title: "Nope",
message: "Your inputs were incorrect.",
preferredStyle: .alert)
alert.addAction( UIAlertAction(title: "Try again",
style: .default,
handler: nil) )
self.present(alert, animated: true, completion: nil)
}
#Maxim you are almost there. Let me add a simple delegate in your code to achieve your goal.
Add code in your textFieldDidEndEditing delegate -
func textFieldDidEndEditing(textField: UITextField) {
if (textField1.text?.count)! > 0 && (textField2.text?.count)! > 0 && (textField3.text?.count)! > 0 {
calculateButton.isEnabled = true
}else{
calculateButton.isEnabled = false
}
}
Now time to calculate the result:
#objc func calculateButtonPressed(sender: UIButton){
if let inputOne = Float(textField1.text!), let inputTwo = Float(textField2.text!), let inputThree = Float(textField3.text!) {
femaleMetaLabel.text = String(111+(1.1*inputOne)+(1.1*inputTwo)-(1.1*inputThree))
}else{
let alert = UIAlertController(title: "", message: "You entered invalid inputs", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(alert, animated: true)
}
}
Hope it will help you. Let me know if you are still having any issue.
I've spent 20+ hours searching/trying different solutions just for this specific problem and cannot make it work. I'm just starting to learn Swift, so be gentile... I made sure to exhaust all options before asking for help.
I have 3 view controllers (VC1: form with 5 text fields, VC2: tableview for displaying gathered data, VC3: 2nd form with 3 text fields and an image picker)
screen shot of storyboard
VC1 gathers the text field data, pass to VC2, and use custom cell #1 to add to the tableview. I used the exact same methods to do the same for VC3 (changing the cell identifier, and using if/else to determine which section to add to) but cannot get any results. At first I thought my data wasn't being passed, but that checks out ("Finihed & Send" button set to alert and prints variable's text) next I thought it was my logic, but custom cell #1 works... I've been staring it this code for so long, I have horrible dreams about it. I feel like this should be obtainable with the techniques I'm applying but wonder if I am I wandering into Core Data territory but just don't know it.
tableview with only 1 custom cell
My intent is to have VC1 add a cell (custom cell 1) at indexPath.row 0 and VC3 to add (custom cell 2) indexPath.row >= 1. Everything works like I want it to with the exception of adding a second custom cell to the tableview.
addWorkViewController
import UIKit
import MapKit
import CoreLocation
class mainVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, CLLocationManagerDelegate, UITextFieldDelegate {
#IBOutlet weak var scrollviewWORK: UIScrollView!
#IBOutlet weak var typeWORK: UISegmentedControl!
#IBOutlet weak var locationWORK: UITextField!
#IBOutlet weak var positionWORK: UISegmentedControl!
#IBOutlet weak var priceWORK: UITextField!
#IBOutlet weak var photo1WORK: UIImageView!
#IBOutlet weak var descriptionWORK: UITextView!
/// Prepare Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.destination {
case is WorkOverview:
let workDest: WorkOverview = segue.destination as! WorkOverview
var cost = ""
var snap = UIImage()
if (priceWORK.text == nil) {
cost = ""
} else {
cost = priceWORK.text!
}
if (photo1WORK.image == nil) {
snap = UIImage()
} else {
snap = photo1WORK.image!
}
workDest.workLocation = locationWORK.text!
workDest.workDescription = descriptionWORK.text!
workDest.workPrice = cost
workDest.workPhoto = snap
case is PlantList:
let plantDest: PlantList = segue.destination as! PlantList
plantDest.placeholder = ""
default:
break
}
}
/// END Segue Preparation
/// Save to List Button
#IBAction func saveToListBTN(_ sender: UIButton) {
performSegue(withIdentifier: "unwindToList", sender: self)
}
/// END Save to List Button
/// Insert Plant
#IBAction func insertPlant(_ sender: UIButton) {
performSegue(withIdentifier: "toPlantListSegue", sender: self)
}
var addedPlant: String? = ""
/// END Insert Plant
/// Clear All Button
#IBAction func clearAllBTN(_ sender: UIButton) {
}
/// END Clear All Button
/// Segmented Controller - Work Type
#IBAction func positionChanged(_ sender: UISegmentedControl) {
switch positionWORK.selectedSegmentIndex {
case 0:
locationWORK.text? += " - Front"
case 1:
locationWORK.text? += " - Back"
case 2:
locationWORK.text? += " - Side"
default:
break
}
}
#IBAction func indexChanged(_ sender: UISegmentedControl) {
switch typeWORK.selectedSegmentIndex {
case 0:
descriptionWORK.text = "Provide and install "
case 1:
descriptionWORK.text = "Replace "
case 2:
descriptionWORK.text = "Remove and dispose of "
default:
break
}
}
/// END Segmented Controller - Work Type
/// ScrollView Keyboard Adjust
func textFieldDidBeginEditing(_ textField: UITextField) {
if (textField == priceWORK){
scrollviewWORK.setContentOffset(CGPoint(x: 0, y: 205), animated: true)
} else {}
}
func textFieldDidEndEditing(_ textField: UITextField) {
scrollviewWORK.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}
/// END Scrollview Keyboard Adjust
/// VIEWDIDLOAD
override func viewDidLoad() {
super.viewDidLoad()
// Toolbar
let toolBar = UIToolbar()
toolBar.sizeToFit()
let backArrow = UIBarButtonItem.init(image: #imageLiteral(resourceName: "backArrow"), style: .plain, target: nil, action: #selector(backArrowClicked))
let spacerA = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let workDoneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneBtnClicked))
let spacerB = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let nextArrow = UIBarButtonItem.init(image: #imageLiteral(resourceName: "nextArrow"), style: .plain, target: nil, action: #selector(nextArrowClicked))
toolBar.setItems([backArrow, spacerA, workDoneBtn, spacerB, nextArrow], animated: false)
toolBar.setItems([backArrow, spacerA, workDoneBtn, spacerB, nextArrow], animated: false)
locationWORK.inputAccessoryView = toolBar
priceWORK.inputAccessoryView = toolBar
descriptionWORK.inputAccessoryView = toolBar
}
/// END VIEWDIDLOAD
/// Toolbar - Done Button
#objc func doneBtnClicked() {
view.endEditing(true)
}
/// END Toolbar - Done Button
/// Arrow to Next TextField
#objc func nextArrowClicked() {
if (locationWORK.isFirstResponder) {
descriptionWORK.becomeFirstResponder()
} else if (descriptionWORK.isFirstResponder) {
priceWORK.becomeFirstResponder()
} else if (priceWORK.isFirstResponder) {
view.endEditing(true)
scrollviewWORK.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}
}
/// END Arrow to Next TextField
/// Arrow to Previous TextField
#objc func backArrowClicked() {
if (locationWORK.isFirstResponder) {
view.endEditing(true)
scrollviewWORK.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
} else if (descriptionWORK.isFirstResponder) {
locationWORK.becomeFirstResponder()
} else if (priceWORK.isFirstResponder) {
descriptionWORK.becomeFirstResponder()
}
}
/// END Arrow to Previous TextField
/// Image Select from Library & Camera
#IBAction func takePhotoONE(_ sender: UIButton) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Want to add a photo?", message: "Please choose a source.", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
}else{
print("Camera is not available")
}
}))
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action:UIAlertAction) in imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Remove Photo", style: .destructive, handler: { (action:UIAlertAction) in self.photo1WORK.image = nil}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
photo1WORK.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
/// END Image Select from Library & Camera
/// GPS Location
let addressManager = CLLocationManager()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let streetAddress = locations[0]
CLGeocoder().reverseGeocodeLocation(streetAddress) { (placemark, error) in
if error != nil
{
print ("Sorry, there has been an error.")
}
else
{
if let place = placemark?[0]
{
if place.subThoroughfare != nil
{
self.locationWORK.text = "\(place.subThoroughfare!) \(place.thoroughfare!)"
}
}
}
}
}
#IBAction func getGPS(_ sender: UIButton) {
// Address
addressManager.delegate = self
addressManager.desiredAccuracy = kCLLocationAccuracyBest
addressManager.requestWhenInUseAuthorization()
addressManager.startUpdatingLocation()
}
/// END GPS Location
}
TableViewController
import UIKit
class WorkOverview: UIViewController {
#IBOutlet weak var listTableView: UITableView!
#IBAction func addWorkBTN(_ sender: UIButton) {
performSegue(withIdentifier: "overviewToWorkSegue", sender: self)
}
#IBAction func unwindToList(segue:UIStoryboardSegue) { }
#IBAction func finishedBTN(_ sender: UIButton) {
let alertController = UIAlertController(title: "Data Pass Test", message:
workLocation, preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default,handler: nil))
self.present(alertController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
property = createArray()
workPJs = workArray()
listTableView.delegate = self
listTableView.dataSource = self
}
var propForm = String()
var propName = String()
var propCity = String()
var propDate = String()
var propDue = String()
var propRep = String()
var workLocation = String()
var workDescription = String()
var workPrice = String()
var workPhoto = UIImage()
var workPJs: [WorkManager] = []
var property: [TaskManager] = []
func workArray() -> [WorkManager] {
var tempWork: [WorkManager] = []
let work1 = WorkManager(location: workLocation, description: workDescription, price: workPrice, photo: workPhoto)
tempWork.append(work1)
return tempWork
}
func createArray() -> [TaskManager] {
var tempProperty: [TaskManager] = []
let prop1 = TaskManager(title: propForm, property: propName, city: propCity, date: propDate, due: propDue, rep: propRep)
tempProperty.append(prop1)
return tempProperty
}
}
extension WorkOverview: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return property.count
} else {
return workPJs.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let prop = property[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "PropertyCell", for: indexPath) as! PropertyCell
cell.setProperty(prop: prop)
return cell
} else if indexPath.section == 1 {
let wrk = workPJs[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "WorkCell", for: indexPath) as! WorkCell
cell.setWork(wrk: wrk)
return cell
}
return UITableViewCell()
}
}
WorkCell class
import UIKit
class WorkCell: UITableViewCell {
#IBOutlet weak var theLocation: UILabel!
#IBOutlet weak var theDescription: UILabel!
#IBOutlet weak var thePrice: UILabel!
#IBOutlet weak var thePhoto: UIImageView!
func setWork(wrk: WorkManager) {
theLocation.text = wrk.location
theDescription.text = wrk.description
thePrice.text = wrk.price
thePhoto.image = wrk.photo
}
}
WorkManager class
import UIKit
class WorkManager {
var location: String
var description: String
var price: String
var photo: UIImage
init(location: String, description: String, price: String, photo: UIImage){
self.location = location
self.description = description
self.price = price
self.photo = photo
}
}
in ViewDidLoad add this code according to names of your cell
tableView.registerNib(UINib(nibName: "cell xib", bundle: nil), forCellReuseIdentifier: "cell name")
in your case you have to register both nib of your custom cell.
i have feelings your section if else condition is wrong. better to debug.
Here, you need to define the second TableViewCell class but in your code only WorkCell class define. so, i hope below link is help you.
UITableview with more than One Custom Cells with Swift
I changed the if statement in cellForRowAt func to a switch case (don't know if it helped or not) but I know adding .reloadData() to my tableview in the viewDidAppear func got it working. Still needs some debugging but that's life.
I have a View controller that has a tableView embedded in a ContainerView and just below the ContainerView I have a UISlider. I have code on a view controller for the UISlider and code on another view controller that controls the table view.
Properties of the UISlider are set based on the selected text field - this section of code works. I am struggling to create a function/feature that will change the textField value when the UISlider is move. I think the UISlider Action needs to on the code that controls the UISlider, but I cannot determine how to cast the value of the UISlider.setvalue between the two viewController as the slider is moved to update the textField located in a tableCell. Hopefully makes some sense.
// UISlider ViewController
override func viewDidLoad() {
super.viewDidLoad()
sliderOutlet.isContinuous = true
sliderOutlet.tintColor = UIColor.green
self.refreshSlider()
}
#objc func refreshSlider() {
sliderOutlet.minimumValue = Float(GlobalSliderValues.minimumValue)
sliderOutlet.maximumValue = Float(GlobalSliderValues.maximumValue)
sliderOutlet.value = Float(GlobalSliderValues.sliderValue)
// if let chgIntValue = Int(GlobalSliderValues.changeValue)
// { sliderOutlet.setValue(Float(Double(chgIntValue)), animated: true)
// }
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(self.refreshSlider), name: Notification.Name("refreshSlider"), object: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self, name: Notification.Name("refreshSlider"), object: nil)
}
TableView Controller
override func viewDidLoad() {
super.viewDidLoad()
mortgageAmount.addTarget(self, action: #selector(chgTextFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
}
#objc func chgTextFieldDidChange(textField: UITextField)
{
if let chgStringValue = mortgageAmount.text
{
if Double(chgStringValue) ?? 1 > 10000 {
let alert = UIAlertController(title: "Input Error", message: "Value cannot be greater than 10000", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
GlobalSliderValues.minimumValue = 10
GlobalSliderValues.maximumValue = 10000
GlobalSliderValues.sliderValue = Int(mortgageAmount.text!)!
GlobalSliderValues.mortageAmountValue = Float(Int(mortgageAmount.text!)!)
NotificationCenter.default.post(name:Notification.Name("refreshSlider"), object: nil)
if let chgIntValue = Int(chgStringValue)
{ GlobalSliderValues.changeValue.setValue(Float(Double(chgIntValue)), animated: true)
}
}
}
#IBAction func valueChanged(_ sender: UISlider) {
mortgageAmount.text = String(format: "%.2f",Double(sender.value))
}
struct GlobalSliderValues {
static var minimumValue = Int()
static var maximumValue = Int()
static var lowerValue = Int()
static var UpperValue = Int()
static var locationValue = Int()
static var sliderValue = Int()
static var sliderChgValue = ""
}
We don't need notification center to deal with refreshing the slider. Since we are using constants to store value your code can be changed as follows
class ViewController: UIViewController {
#IBOutlet weak var sliderOutlet: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
sliderOutlet.isContinuous = true
sliderOutlet.tintColor = UIColor.green
}
#objc func refreshSlider() {
DispatchQueue.main.async {
self.sliderOutlet.minimumValue = Float(GlobalSliderValues.minimumValue)
self.sliderOutlet.maximumValue = Float(GlobalSliderValues.maximumValue)
self.sliderOutlet.value = Float(GlobalSliderValues.sliderValue)
print(self.sliderOutlet.minimumValue)
print(self.sliderOutlet.maximumValue)
print(self.sliderOutlet.value)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.refreshSlider()
}
}
I entered mortgage amount as so 1098 so slider look like below
I have a question regarding interesting behavior that I have on a UIScrollView. Here is the relevant code.
class TipCreationViewController: UIViewController, MKMapViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextViewDelegate, UITextFieldDelegate {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var contView: UIView!
var iView: UIImageView?
var currentHeight: CGFloat = 0 {
didSet {
self.scrollView.contentSize = CGSize(width: self.scrollView.contentSize.width, height: self.currentHeight)
}
}
private var imageAttached: UIImage?
let imagePicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
self.imagePicker.delegate = self
self.imagePicker.allowsEditing = false
self.currentHeight = 150
}
#IBAction func cameraWasPressed(sender: AnyObject) {
imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
let alertViewController = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
let actionFromLibrary = UIAlertAction(title: "From Library", style: .Default) { (_) -> Void in
self.imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(self.imagePicker, animated: true, completion: nil)
}
let actionFromCamera = UIAlertAction(title: "From Camera", style: .Default) { (_) -> Void in
self.imagePicker.sourceType = UIImagePickerControllerSourceType.Camera
self.presentViewController(self.imagePicker, animated: true, completion: nil)
}
let actionCancel = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alertViewController.addAction(actionFromLibrary)
alertViewController.addAction(actionFromCamera)
if imageAttached != nil {
let actionDeletePhoto = UIAlertAction(title: "Remove Image", style: .Default, handler: { (_) -> Void in
self.deletePhotoIfThere()
})
alertViewController.addAction(actionDeletePhoto)
}
alertViewController.addAction(actionCancel)
alertViewController.view.tintColor = SHREDLIGHTS_BLUE
self.presentViewController(alertViewController, animated: true, completion: nil)
}
//THIS SEEMS TO BE THE FUNCTION IN QUESTION...
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
deletePhotoIfThere()
self.imageAttached = pickedImage
let height = self.view.frame.width * pickedImage.scale
self.iView = UIImageView(frame: CGRectMake(0, self.currentHeight, self.contView.frame.width, height))
self.iView!.contentMode = UIViewContentMode.ScaleAspectFit
self.iView!.image = pickedImage
self.currentHeight += height
self.contView.addSubview(self.iView!)
}
self.dismissViewControllerAnimated(true, completion: nil)
}
func deletePhotoIfThere() {
if let iv = self.iView {
self.currentHeight -= iv.frame.height
iv.removeFromSuperview()
self.iView?.removeFromSuperview()
self.iView = nil
}
}
}
So, the way that this works is that the user hits the cameraWasPressed button. This displays an action sheet that will allow the user to choose if they want to take a photo or pick one from their library. Now, the problems that I think I have is with imagePickerController method. All works as I expect. An image view is appended to the contView and the currentHeight will increase when the user picks a photo from the camera or from the library. Except one interesting piece of behavior. When the user takes a picture from the camera, the scroll view that I have freezes. However, when the user picks a picture from the library, the scroll view will work. Does anybody know why this discrepancy in regards to why a photo from the camera will cause a UIScrollView to stop working and one from the library will not cause any problems?