Why is "1925-1-23" and "1924-2-5" being excluded when I try to call an image with them in date picker? I am successfully able to call images with every date in between the two dates above. Why are the dates "1925-1-23" and "1924-2-5" the only dates not calling images.
import UIKit
public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs === rhs || lhs.compare(rhs) == .OrderedAscending
}
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedDescending
}
extension NSDate: Comparable { }
class ViewController: UIViewController {
#IBOutlet weak var displayAnimal: UIImageView!
#IBOutlet weak var dateWheel: UIDatePicker!
#IBAction func goButton(sender: UIDatePicker)
{
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd"
dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
{
let dateStringFormatter = NSDateFormatter()
dateStringFormatter.dateFormat = "yyyy-MM-dd"
dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
let rabbit1A = dateStringFormatter.dateFromString("1924-2-5")
let rabbit2A = dateStringFormatter.dateFromString("1925-1-23")
if(dateWheel.date.compare(rabbit1A!) == NSComparisonResult.OrderedDescending &&
dateWheel.date.compare(rabbit2A!) == NSComparisonResult.OrderedAscending)
{
// set the image of UIImageView
displayAnimal.image = UIImage(named: "rabbit")
}
In your IBOutlet:
#IBAction func selectDateButton(sender : UIDatePicker) {
// set the date criteria here
if(sender.date.compare(dateA) == NSComparisonResult.OrderedAscending && sender.date.compare(dateB) == NSComparisonResult.OrderedDescending) {
// set the image of UIImageView
displayAnimal.image = UIImage(named: "rabbit")
}
}
where dateA and dateB are the date (in form of NSDate) that falls into the criteria of displaying rabbit image.
A date picker won't talk to an image view. A date picker is a UIControl.
The logic to do what you want belongs in your view controller.
You would set up an IBOutlet to your date picker.
You'd add an OK button to your view controller in IB that linked to an IBAction method.
In that IBAction method you would look at the date property of the picker (using the picker's outlet.) If the date matches one of your magic dates, you'd have code that would load one of your images into an image view that was linked to another IBOutlet in your view controller.
Break it down into baby steps. Hook up the outlets and actions. At first just put a println("In button action") in your IBAction method. Next, fetch the date from the picker and log that in your IBAction.
Next, figure out how to write a switch statement that matches your different dates and prints statements when you match your different dates. That will require a detour into the docs to read about Swift's very powerful switch statement.
Next figure out how to load your different images from your array of names and install them into an image view on your view controller when you click a button. (First set up an Int instance variable imageIndex that starts at 0, and have a button press load an image name from you array of image names, increment the index for next time, and then installs the loaded image into your image view.
Finally, adjust your switch statement so your various magic dates load the desired image into your image view.
Related
I want to get initial value of timePicker, value changes when I am just scrolling time. Please watch photos it will be more clear to understand what I want.
https://imgur.com/a/3Hg69uR
#IBAction func datePickerChanged(_ sender: Any) {
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
dateFormatter.dateFormat = "HH:mm"
let strDate = dateFormatter.string(from: datePicker.date)
datePickerLb.text = strDate
}
All you need is to update the label inside your viewDidLoad method. I would move the date formatter declaration out of that method to avoid creating a new one every time the value changes. Note that you should use timeStyle or dateFormat but not both. When displaying dates to the end user you should always respect the devices locale and settings so you should choose timeStyle in this case:
let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
return dateFormatter
}()
override func viewDidLoad() {
super.viewDidLoad()
// your code
// you can update the label here
// datePickerLb.text = dateFormatter.string(from: datePicker.date)
// or manually send the valueChanged action to force the update at view did load
datePicker.sendActions(for: .valueChanged)
}
#IBAction func datePickerChanged(_ datePicker: UIDatePicker) {
datePickerLb.text = dateFormatter.string(from: datePicker.date)
}
The answer by #Leo is practical. One thing to add is that if you wanted the date updated while picker it is rolling then, unfortunately, it is impossible with UIDatePicker itself. This is because UIDatePicker is not a subclass of UIPickerView and it manages a UIPickerView internally. The the solution here might be use a custom UIPickerView. Then for that UIPickerView you can implement it's delegate method like this:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch component {
case 0:
currentTime.hours = pickerView.selectedRow(inComponent: 0)
return "\(row) Hour"
case 1:
currentTime.minutes = pickerView.selectedRow(inComponent: 1)
return "\(row) Minute"
case 2:
currentTime.seconds = pickerView.selectedRow(inComponent: 2)
return "\(row) Second"
default:
return ""
}
}
currentTime var should, for example, have a didSet to update some view elements when it changes.
I'm stuck: I have a TableView populated by .xib cells that I made. Each of these cells contains an editable TextView.
I'm trying to save on my Firebase database the text that the user input in those TextViews. I don't want to implement any button, the text should be saved as soon as the TextView editing end.
I tried to connect the TextView from the .xib file to the UITableViewCell class but it doesn't allow me to connect it as an IBAction but only as outlet or outlet connection.
Please Help me, thanks!
screenshot
You need to implement the UITextFieldDelegate in your
UITableViewCell class.
Connect the delegate of the UITextView to the cell class.
Do whatever you want in the func textViewDidEndEditing(UITextView) which you need to implement in your cell class.
Here you can read more: https://developer.apple.com/documentation/uikit/uitextviewdelegate/1618603-textviewshouldendediting?changes=_2
I solved replacing the TextViews with TextFields that could look the same but could be linked to the UITableViewCell.swift as IBAction.
Thus I wrote the code to update the "comments" section of my database inside the IBAction:
#IBAction func commentTextFieldToggle(_ sender: UITextField) {
if commentTextField.text != "" {
let comment = commentTextField.text
// I declared the next 7 constants to retreive the exact position of the string "comment" that I want to change
let date = dateLabel.text!
let time = timeLabel.text!
let year = date.suffix(4)
let day = date.prefix(2)
let partialMonth = date.prefix(5)
let month = partialMonth.suffix(2)
//I use this "chosenDate" constant to retreive the database query that I previously saved using the date in the below format as index:
let chosenDate = "\(year)-\(month)-\(day) at: \(time)"
let commentsDB = Database.database().reference().child("BSL Checks")
commentsDB.child((Auth.auth().currentUser?.uid)!).child(String(chosenDate)).child("Comments").setValue(comment) {
(error, reference) in
if error != nil {
print(error!)
} else {
print("User Data saved successfully")
}
}
}
}
Based on my previous question in here . I have two datePicker let say A and B. I want to set maximum of A is B.date and minimum of B is A.date.
But when i change the B value, the A maximum value still in old B maximum value. I dont have any idea about this.
let date = NSDate()
self.datePickerFrom.maximumDate = date as Date
self.datePickerTo.minimumDate = datePickerFrom.date
Any sugest and answer will helpfull for me. Thanks in Advance.
You need to tell some function in your view controller that the date pickers have changed. To do that, declare some #IBAction in your view controller that looks like this:
#IBAction func datePickerChanged(sender: UIDatePicker)
{
print("date has been set to \(sender.date)")
}
Then click on your date pickers in your storyboard or XIB file and connect the "Valued Changed" event to this new method.
Then try running it to see if the print line prints in the console.
If it does, you can fill out more of that function. Perhaps something like this:
#IBAction func datePickerChanged(sender: UIDatePicker)
{
if sender == self.datePickerFrom
{
self.datePickerTo.minimumDate = sender.date
}
if sender == self.datePickerTo
{
self.datePickerFrom.maximumDate = sender.date
}
}
I have dynamic tableview, wherein one of the cell (duration) when tapped opens another view controller which is a list of duration viz (30 min, 1 hour, 2 hours and so fort). One of the durations when selected should display the selected duration in the first view controller. I am able to pass the data back to first view controller using unwind segue but unable to display the passed value. DOn't know whats missing.
I am displaying the code below:
FIRST VIEW CONTROLLER (CALLING)
#IBAction func unwindWithSelectedDuration(segue:UIStoryboardSegue) {
var cell = tableView.dequeueReusableCellWithIdentifier("durationCell") as! durationTableViewCell
if let durationTableViewController = segue.sourceViewController as? DurationTableViewController,
selectedDuration = durationTableViewController.selectedDuration {
cell.meetingDurationCell.text = selectedDuration
duration = selectedDuration
}
SECOND VIEW CONTROLLER (CALLED)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SaveSelectedDuration" {
if let cell = sender as? UITableViewCell {
let indexPath = tableView.indexPathForCell(cell)
if let index = indexPath?.row {
selectedDuration = durationList[index]
}
}
}
}
tableView.dequeueReusableCellWithIdentifier should only be called within tableView:cellForRowAtIndexPath:. It has no use outside this context.
The easiest fix is to just reload the table once you have stored the selected duration:
#IBAction func unwindWithSelectedDuration(segue:UIStoryboardSegue) {
if let durationTableViewController = segue.sourceViewController as? DurationTableViewController {
selectedDuration = durationTableViewController.selectedDuration
tableView.reloadData()
}
}
Note that this assumes you only need one selectedDuration for your whole table, rather than one per row. If you need one per row, I assume you have them stored in an array somewhere, so it is that array that should be updated instead before the reloadData.
I have an app that I am converting from objective-c to Swift and am also changing it to use dynamic (rather than static) tables. I can load the cells with entity rows but I have been unable to figure out how to reference the UISwitch value in the #IBAction function in order to save it to CoreData.
Can anyone point me to simple example of how to do this?
In storyboard, link the UISwitch in your prototype cell to the #IBAction handler in the view controller. In the handler, determine the core data object and manipulate as desired.
Assuming you have a fetched results controller (recommended):
#IBAction didFlipSwitch(sender: UISwitch) {
let point = sender.convertPoint(CGPointZero, toView:tableView)
let indexPath = tableView.indexPathForRowAtPoint(point)
let object = fetchedResultsController.objectAtIndexPath(indexPath) as! Thing
thing.flag = sender.on
}
Addition:
Pursuant to your question: If you are not using a fetched results controller (though this is not recommended), you are presumably using an Array like [Thing]. You would replace the one line with something like:
let object = dataArray[indexPath.row] // no need to cast to Thing
Second, if you need access to other values in the cell, you can get to the cell and its elements with
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomCell
let textToRetrieve = cell.textField?.text
However, this is not a good method, because you are getting data from your UI elements. Instead you should always store the data in your model, not in a table view row!
Thus, the proper text attribute of your Thing should already have been set by the UITextFieldDelegate implementation. (You can get the indexPath and thence the desired object in pretty much the same way as above, with convertPoint and indexPathForRowAtPoint.)
Consequently, when you flip the switch and retrieve the Core Data object as shown above, the text attribute be readily available (though you will probably not need it).
Ultimately I resolved this by using both cellForRowAtIndexPath to load the cells from my data model in my custom UITableViewController class and the following code in my custom UITableViewCell class. (Probably this is what Mundi was suggesting but if so I did not understand him.)
class CREWTableViewCell: UITableViewCell {
#IBOutlet weak var myTextView: UITextView!
#IBOutlet weak var mySwitch: UISwitch!
#IBAction func changedSwitch(sender: UISwitch) {
var newDescription = self.myTextView.text // value from cell
var newSwitchValue = self.mySwitch.on // value from cell
var fetchRequest = NSFetchRequest(entityName: "Switch")
var pred1 = NSPredicate(format: "(viewName = %#)",viewName)
var pred2 = NSPredicate(format: "(switchDescription = %#)",newDescription)
fetchRequest.predicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: [pred1, pred2])
// Execute the fetch request
var error: NSError? = nil
if let fetchResults = context.executeFetchRequest(fetchRequest, error: &error) as? [Switch]
{
var recordCount = 0
recordCount = fetchResults.count
if recordCount == 1 {
var appConfig = fetchResults [0]
appConfig.switchValue = newSwitchValue
if !managedObjectContext!.save(nil) {
NSLog("Unresolved error ")
abort()
}
}
}
}