Save tableview textfields to an array of custom objects - ios

I´m searching for a way to save the data a user enters in two textfields in a tableview. The user has to enter the name and the height of person in a tableview and I want to save it to a custom array.
struct PersonData {
var name: String
var height: Int
init(name: String, height: Int) {
self.name = name
self.height = height
}
}
I´ve searched and i found this Swift: retrieving text from a UITextField in a custom UITableViewCell and putting it in an array but still got two questions.
How i add item to my custom array? I try it with this:
personData[textField.tag].name = textField.text!
Isn´t a easier way to do it?
Thank you!!

If I understood your question properly then heres a possible solution.
You initialise an array of type PersonData. Then you make an object of type PersonData. Whenever you have some info, you store it in this object and append the object to the array created.
let array = [PersonData]()
let personDataObject = PersonData()
//After you store the values in the object you add the object to you array.
personDataObject.name = textField1.text
personDataObject.height = textField2.text //You need to convert this to Int. Try personDataObject.height = textField2.text as? Int or personDataObject.height = Int(textField2.text)
array.append(personDataObject)

Related

Avoid duplicates while adding in dictionary

I have a dictionary in which I'm adding values like so...
var mydictionary = ["id": "", "quantity": "","sellingPrice":""] as [String : Any]
dictionary["id"] = product?.id
dictionary["quantity"] = product?.quantity
dictionary["sellingPrice"] = product?.theRate
And these values I added to an array like so...
self.arrayOfDictionary.append(mydictionary)
But if arrayOfDictionary already contains mydictionary, I don't want to add it. Else, I want to add it.
The basic idea here is to add data from collection view items to array of dictionary. When I click on the buttons that I have on each collection view item the data on it is added to an array of dict. while at the same time showing those data in a tableviewcell. But when I navigate back from the tableview & visit the collectionview items again and click on some other collecn.view item, so as to add them to the array of dictionary as before, then the item that was added initially to the array of dictionary gets added again. This has to be somehow prevented.
As suggested by another SO user something like this was tried to prevent this duplication...
if self.arrayOfDictionary.contains(where: { (dict) -> Bool in
"\(dict["id"] ?? "")" != "\(dictionary["id"] ?? "")"}) {
self.arrayOfDictionary.append(dictionary)
}
But this doesn't seem to work. With this nothing is added to the array and its totally empty. Hope somebody can help...
Try this code to avoid duplication
I hope "id" value will be unique in your dictionary.
var mydictionary = ["id": "1", "quantity": "","sellingPrice":""] as [String : Any]
var arrayOfDictionary = [Dictionary<String, Any>]() //declare this globally
let arrValue = arrayOfDictionary.filter{ (($0["id"]!) as! String).range(of: mydictionary["id"]! as! String, options: [.diacriticInsensitive, .caseInsensitive]) != nil }
if arrValue.count == 0 {
arrayOfDictionary.append(mydictionary)
}
I've got better idea then every time you perform loop to check unique ness.
Maintain one Bool array of same size of your collectionView Items array with predefined false values each.
When you click on button of collection View item, change flag of Bool array with same index. And simultaneously you can disable the button also(if you want). Otherwise whenever user clicks on button, just check flag from Bool array and add Dictionary to new array as needed.
Here, your new array will be performed and you will same process and time of looping also.
One way to approach the problem could be to construct a structure which contains product details:
/// Details Of A Product
struct ProductDetails{
var id: String!
var quantity: Int!
var sellingPrice: Int!
}
Then create a dictionary which stores the product details with the key being the "ID" e.g:
var products = [String: ProductDetails]()
You could then create a product like so:
let productA = ProductDetails(id: "1", quantity: 100, sellingPrice: 10)
To add a unique product to your dictionary you could use a function like this:
/// Adds A Product To The Products Dictionary
///
/// - Parameter product: ProductDetails
func addProductDetails(_ product: ProductDetails){
//1. If A Product Exists Ignore It
if products[product.id] != nil{
print("Product With ID \(product.id!) Already Exists")
}else{
//2. It Doesn't Exist So Add It To The Dictionary
products[product.id] = product
}
}
I tested this quickly and it won't allow products which have duplicate ID's. although of course you could change the parameter as needed.

How can I access an item from an array dynamically with Swift

I've got an Array that I'm using to populating the rows of a UITableView.
After a row is selected I need to retrieve information from the Array based on the row selected to populate some outlets (labels, textfields, etc.)
For example:
I create an itemSelected variable in the didSelectRowAtIndexPath in my ViewController for the TableView which I set to indexPath.row
itemSelected = indexPath.row
Then in my viewDidLoad for my otherViewController I need to retrieve the info by
array[itemSelected]
But, I get a compiler error that says: "Expression resolves to unused i-value"
In here you simply accessing the array but not calling any value. As a example if you have a key call "Name" in your array and you want to set it to a UILabel just do it as this.
self.Name.text = array[itemSelected].valueForKey("Name") as! String
if not just do something with it.
self.Name.text = array[itemSelected] as! String
OR
print(array[itemSelected])

Multidimensional Array Looping in cellForRowAtIndexPath Swift

I have a multidimensional array that I want to display the values of onto one UILabel in each respective cell.
My arrays look like this:
var arrayExample = [["beverages", "food", "suppliers"]["other stuff, "medicine"]]
I'm looping through these values in the cellForRowAtIndexPath in order for it to display on different cells (on a UILabel) the appropriate values:
if let onTheLabel: AnyObject = arrayOfContactsFound as? AnyObject {
for var i = 0; i < objects!.count; i++ {
cell?.contactsUserHas.text = "\(onTheLabel[indexPath.row][i])" as! String
print("arrayOfContactsFound Printing! \(onTheLabel)")
}
}
When printing to the console I get:
arrayOfContactsFound Printing! (
(
beverages,
"supply chain",
pharmacuticals
)
)
But on my label I get "beverages". That's it. How can I get the other 2 values (or X amount if there are more or less than 3 values)?
My for in loop is obviously not doing the trick. Assuming I can optimize/fix that to display all the values?
Thanks in advance.
In your loop you're setting the text of your label multiple times. Each time you set it it doesn't accumulate, it completely replaces the current text with the new text. You'll want something like this:
// Remove the cast and the loop in your code example, and replace with this
let items = arrayOfContactsFound[indexPath.row]
let itemsString = items.joinWithSeparator(" ")
cell?.contactsUserHas.text = itemsString
Another thing to note is your cast doesn't quite make a lot of sense.
var arrayExample = [["beverages", "food", "suppliers"]["other stuff, "medicine"]]
So arrayExample is of type [[String]]. I'm assuming each cell in your table view represents one of the arrays of strings in your array. So each cell represents one [String]. So your items should be arrayExample[indexPath.row]. The cast to AnyObject doesn't make too much sense. If anything you'd be casting it to [[AnyObject]], but there's no reason to because the compiler should already know it's [[String]].

Swift - filter Realm objects via UISearchBar in a UICollectionView

This is my Realm object, basically an image with some tag attached.
class AllTags: Object {
dynamic var singleTag = ""}
class Photo: Object {
var myTags: [String] {
get {
return _backingNewTags.map { $0.singleTag }
}
set {
_backingNewTags.removeAll()
_backingNewTags.appendContentsOf(newValue.map({ AllTags(value: [$0]) }))
}
}
let _backingNewTags = List<AllTags>()
override static func ignoredProperties() -> [String] {
return ["myTags"]
}
dynamic var imagePath = ""}
I have my collectionView, I can see all my photo and when pressing an image I can see my tags, so everything is working correctly.
I have added my UISearchBar, added the txtSearchbar.delegate = self and using let data = realm.objects(AllTags).map { $0.singleTag } I can print ALL the tags inside my database.
I just need to filter in real time while I type the CollectionView cells via the UISearchBar so it shows only the images tagged with the word I'm typing. Basic.
I've been following this tutorial to filter in the collectionView - https://github.com/codepath/ios_guides/wiki/Search-Bar-Guide#example-searching-a-collection-view - After 11 hours, I can't figure out how to make it works with Realm. With hardcoded Array like the example I can make it works.
In Realm, you can filter a Results<T> based on what you're looking for. For example:
let data = realm.objects(AllTags).filter("singleTag CONTAINS %#", searchTerm)
I'm wondering, however, why you're converting your _backingNewTags to an Array [String]? Why can't you just access the tags directly? This will be much more memory & CPU efficient, and will simplify your code...

Get an Int out of an UILabel Swift

I have the problem, to have a high amount of buttons which have a number as their label, so i thought i could take the label as an integer instead of creating an action for every button?!
#IBAction func NumberInput(sender: UIButton) {
var input:Int = sender.titleLabel as Int
}
If you want to do this, you can convert the string to an Int by using string.toInt() such as:
if let input = sender.titleLabel?.text?.toInt() {
// do something with input
} else {
// The label couldn't be parsed into an int
}
However, I'd suggest either using UIView.tag or subclassing UIButton and adding an Int property to it to accomplish this, in case you ever change the display of your labels.
You should make sure that the text exists
var input:Int = (sender.titleLabel.text! as NSString).integerValue
You can't convert a UILabel to an Int. I think you want this instead:
var input : Int? = sender.titleLabel.text?.toInt()
Another way to convert a label in swift:
let num = getIntFromLabel(labelView)
connect all your buttons to 1 IBAction. then create the following variable and the set/get methods based on how you will use it.
note: "something" is a UILabel. The variable I wrote below should help you do conversions easily and with cleaner syntax. "newValue" comes with all setter methods. It basically takes into account any value that could possibly used to set "num" to a new value.
var num : Int {
get {
return Int(something!)!
}
set {
something.text = Int(newValue)
}
}
For Swift 3, what you can do is to directly convert it from an String input to an integer, like this
Int(input.text!)
And then, if for any reason, if you wish to print it out or return is as a String again, you can do
String(Int(input.text!)!)
The exclamation mark shows that it is an optional.

Resources