So, i have a file data.swift with some informations
class Data {
var agen = [… ]
var tours = [… ]
var marseille = [… ]
……
}
In another viewcontroller, i m trying to get back a value from above with this.
I can get back a particular value with with command with success :
let entry = data.agen[indexPath.row]
It’s working but I would like set a variable in this command, I put this
var passedValue:String!
// passedValue coming from a segue from a previous VC
// passedValue could be "agen", "tours",”marseille” ...
let entry = data.passedValue[indexPath.row]
But it's not working message error told me "data doesn't have a member named "passedValue"
How could i set properly the variable ?
what about a slightly different syntax
class Data {
var agen = ["A","B","C"]
var tours = ["D","E"]
var marseille = ["F","G","H"]
subscript(index: String) -> [String]! {
switch index {
case "agen" : return agen
case "tours" : return tours
case "marseille" : return marseille
default: return []
}
}
}
let key = "agen"
let data = Data()
print(data[key][1])
(maybe make a bit more error prof)
Other solution is to create classes/structs for 'agen','tours', etc.
And set it in the Data object
class Data {
var agen = [Agen(title), Agen(title2)]
var tours = [Tour(title), Tour(title2)]
…… }
Because, probably you want to show some info about the object in tableView later, so you could go like this:
title.text = tour.title
subtitle.text = tour.placeName
imageView.image = tour.photos[1]
Related
I have product class like the code below:
class Product {
var productID = ""
var hasBeenAddedToWishList = false
}
and then I have two arrays of product
let wishListedProduct = [productx,producty,productz] // from core data
let productList = [productx,producty,productz] // from server
I want to give filled love icon, if the user previously has added the product to the wishlist in core data.
so I want to make a looping between to arrays above, so if the product in the first index of wishListedProduct has the same ID with the first indeex of productList, then I need to change the property of hasBeenAddedToWishList to true. how to do that ?
I have tried with the code below but I can't get what I want
for i in theWishListProducts {
products.map {
if $0.productID == i.productID {
$0.hasBeenAddedToWishList = true
}
}
}
For example:
let wishListedProduct : [Product] = // whatever
let productList : [Product] = // whatever
let wishListedIds = wishListedProduct.map {$0.productID}
for product in productList {
if wishListedIds.contains(product.productID) {
product.hasBeenAddedToWishList = true
}
}
I need to know a good solution in Swift for the below problem I am facing.
I have an array of models declared as var dataArray = [PlanModel]().
class PlanModel: {
var isPurchased:String?
var planName:String?
}
Now I get data from the server and I fill the dataArray with the models. The dataArray consists of 3 models. The value of models are:
Model 1:
isPurchased = "true"
planName = "Question"
Model 2:
isPurchased = "true"
planName = "Personal"
Model 3:
isPurchased = "false"
planName = "Full"
What I need is to reduce this array by checking if the plan is purchased by checking value of isPurchased. If it's true remove it from array, if its false, then keep that in the array.
Please tell me what would be the simpler and efficient way of doing this in Swift?
You can use the filter function
var reducedArray = dataArray.filter {$0.isPurchased == "false"}
This will check each element of the dataArray and if the elements isPurchased is "false" it will keep it
You can use filter with contains function
Model Class:
class PlanModel {
var isPurchased:String?
var planName:String?
init(isPurchased:String?, planname:String?) {
self.isPurchased = isPurchased
self.planName = planname
}
}
override func viewDidLoad() {
super.viewDidLoad()
var plan = [PlanModel]()
plan.append(PlanModel(isPurchased: "true", planname: "Question"))
plan.append(PlanModel(isPurchased: "true", planname: "Personal"))
plan.append(PlanModel(isPurchased: "false", planname: "Full"))
// Filter function
plan = plan.filter {
($0.isPurchased?.contains("false"))!
}
print(plan.count)
// 1
}
Create a filtering function:
func notPurchased(planModel: PlanModel) -> Bool{
return planModel.isPurchased == "false"
}
and use the Array filter function passing in your function
let filteredArray = dataArray.filter(notPurchased)
After post my solution, let me tell you that it's better change isPurchased type from String to Bool.
And now...
class PlanModel
{
var isPurchased:String?
var planName:String?
}
let p1: PlanModel = PlanModel()
p1.isPurchased = "true"
p1.planName = "Question"
let p2: PlanModel = PlanModel()
p2.isPurchased = "true"
p2.planName = "Personal"
let p3: PlanModel = PlanModel()
p3.isPurchased = "false"
p3.planName = "Full"
var plans: [PlanModel] = [ p1, p2, p3 ]
// Filter elements with `isPurchased` property
// set to `true`. As isPurchased is marked as an
// `Optional` type I check that it's not nil before
// process it
plans = plans.filter()
{
guard let isPurchased = $0.isPurchased else
{
return false
}
return isPurchased == "true"
}
plans.forEach()
{
if let planName = $0.planName
{
print(planName)
}
else
{
print("unnamed")
}
}
Since you're looking for removing the item from array itself if it meets certain condition you can do the following code:
dataArray = dataArray.filter({ $0.isPurchased == "False"})
i find this is one of the best approaches and i was using Swift 3
Now on the side note, i recommend using structs instead of classes for models
I have this class
class InboxInterests {
var title = ""
var eventID = 0
var count = ""
var added = 0
init(title : String, eventID : NSInteger, count: String, added : NSInteger) {
self.title = title
self.eventID = eventID
self.count = count
self.added = added
}
}
And i use it like this
var array: [InboxInterests] = [InboxInterests]()
Add item
let post = InboxInterests(title: "test",eventID : 1, count: "test", added: 0)
self.array.append(post)
I want to find the index by eventID key and change the value of added key in the same index
How is that possible?
For me, the above answer did not work. So, what I did was first find the index of the object that I want to replace then using the index replace it with the new value
if let row = self.upcoming.index(where: {$0.eventID == id}) {
array[row] = newValue
}
In Swift 5.0:
if let row = self.upcoming.firstIndex(where: {$0.eventID == id}) {
array[row] = newValue
}
Since you are using a class, use filter and first to find the value:
array.filter({$0.eventID == id}).first?.added = value
In this you:
filter the array down to elements that match the event ID
pick the first result, if any
then set the value
This works since classes are pass by reference. When you edit the return value from array.filter({$0.eventID == id}).first?, you edit the underlying value. You'll need to see the answers below if you are using a struct
EDIT: In Swift 3 you can save yourself a couple of characters
array.first({$0.eventID == id})?.added = value
EDIT: Swift 4.2:
array.first(where: { $0.eventID == id })?.added = value
array.filter {$0.eventID == id}.first?.added = value
The filter operator is not the best in this case, it works for some of you because classes are passed by reference.
Explanation: (You can copy the following code in a playground if you want to verify it).
class Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook.filter{ $0.id == 1 }.first?.title = "modified"
arrayBook.forEach { book in
print(book.title)
}
Arrays are copied by value not reference, so when you are using filter you are creating a new array (different than the initial), but when you modify the new one, the initial one gets modified too because both are pointing to the same class (classed are passed by reference), so after the filter your array will have changed and the new one gets deallocated. So in this case it will print "default", "default" and then "default, "modified".
What happens if you change class for struct, the value will be passed by value not reference so you will have 2 arrays in memory with different values, so if you go through arrayBooks again it will print before the filter "default","default", and then "default", "default" again. Because when you are using the filter you are creating and modifying a new array that will get deallocated if you do not store it).
The solution is using map, creating a new array with all the values but with the modified items or fields that we want and then replace our array with the new one. This will print "default", "default" before the map, and then "default", "modified"
This will work with structs, classes and everything that you want :).
struct Book {
let id: Int
var title = "default"
init (id: Int) {
self.id = id
}
}
var arrayBook = [Book]()
arrayBook.append(Book(id: 0))
arrayBook.append(Book(id:1))
arrayBook.forEach { book in
print(book.title)
}
arrayBook = arrayBook.map{
var mutableBook = $0
if $0.id == 1 {
mutableBook.title = "modified"
}
return mutableBook
}
arrayBook.forEach { book in
print(book.title)
}
array = array.map { $0.eventID == id ? newValue : $0 }
If you conform your class to Equatable then this would work:
extension Array where Element: Equatable {
#discardableResult
public mutating func replace(_ element: Element, with new: Element) -> Bool {
if let f = self.firstIndex(where: { $0 == element}) {
self[f] = new
return true
}
return false
}
}
Use like this:
array.replace(prev, with: new)
This question already has an answer here:
Table view from array index out of range
(1 answer)
Closed 7 years ago.
PROBLEM:
What I'm looking for is to display this info in a table so I think I need:
MyHouses1[section][row].getAddressDetails()
How do I properly define MyHouses1?
import UIKit
class House {
var address = "Address"
var street = "Street"
var city = "City"
var state = "State"
var zip = "Zip"
func getAddressDetails() -> String {
return "\(address) \(street) \(city) \(state) \(zip)"
//return "\(address) \(street)"
}
func getCityState() -> String {
return "\(city) - \(state)"
}
}
class newhouse: House {
var lighting = "crappy"
var plumbing = "sucks"
var heating = "heats good"
var cooling = "cools good"
var repairs = "needs alot of repairs"
func getFixtureDetails() -> String {
return "\(lighting) \(plumbing) \(heating) \(cooling)"
}
}
// THIS WORKS
var MyHouses: [newhouse] = []
MyHouses.append(newhouse())
MyHouses[0].address = "test"
MyHouses[0].getAddressDetails()
// THIS DOESN'T WORK
var MyHouses1: [[newhouse]] = [] // No Error Yet
MyHouses1.append // Getting an error here, not sure how to append
Details: in order to post the website wants me to add more details.....so here I am adding more details lol
You could do this..
var MyHouses1: [[newhouse]] = []// No Error Yet
var houses = [newhouse]() //Initialize your `newhouse` array here
for i in 0...4 {
houses += [newhouse()]
}
MyHouses1 += [houses]
print("\(MyHouses1[0][0].city)") // will print "City"
I have an array of type "drugList", and they are derived from a struct "DrugsLibrary":
struct DrugsLibrary {
var drugName = ""
var drugCategory = ""
var drugSubCategory = ""
}
var drugList = [DrugsLibrary]()
//This is the dictionary i'm trying to build:
var dictionary = ["": [""," "]]
My data model is initialized using this function:
func createDrugsList() {
var drug1 = DrugsLibrary()
drug1.drugName = "drug1"
drug1.drugCategory = "Antibiotics"
drug1.drugSubCategory = "Penicillins"
self.drugList.append(drug1)
var drug2 = DrugsLibrary()
drug2.drugName = "drug2"
drug2.drugCategory = "Antibiotics"
drug2.drugSubCategory = "Penicillins"
self.drugList.append(drug2)
var drug3 = DrugsLibrary()
drug3.drugName = "drug2"
drug3.drugCategory = "Antibiotics"
drug3.drugSubCategory = "Macrolides"
self.drugList.append(drug3)
}
my problem is that i'm trying to create a dictionary from the drugList where the key is the drugSubCategory and the value is the drug name. The value should be an array if there are several drugs in this subcategory
for example, the dictionary should look something like this for this example:
dictionary = [
"Penicillins": ["drug1","drug2"]
"Macrolides": ["drug3"]
]
I tried this method:
for item in drugList {
dictionary["\(item.drugSubCategory)"] = ["\(item.drugName)"]
}
this gave a dictionary like this, and it couldn't append drug2 to "Penicllins":
dictionary = [
"Penicillins": ["drug1"]
"Macrolides": ["drug3"]
]
So I tried to append the items into the dictionary using this method but it didn't append anything because there were no common items with the key "" in the data model:
for item in drugList {
names1[item1.drugSubCategory]?.append(item1.drugName)
}
Anyone knows a way to append drug2 to the dictionary?
I would appreciate any help or suggestion in this matter.
You need to create a new array containing the contents of the previous array plus the new item or a new array plus the new item, and assign this to your dictionary:
for item in drugList {
dictionary[item.drugSubCategory] = dictionary[item.drugSubCategory] ?? [] + [item.drugName]
}
You can use .map and .filter and Set to your advantage here. First you want an array of dictionary keys, but no duplicates (so use a set)
let categories = Set(drugList.map{$0.drugSubCategory})
Then you want to iterate over the unique categories and find every drug in that category and extract its name:
for category in categories {
let filteredByCategory = drugList.filter {$0.drugSubCategory == category}
let extractDrugNames = filteredByCategory.map{$0.drugName}
dictionary[category] = extractDrugNames
}
Removing the for loop, if more Swifty-ness is desired, is left as an exercise to the reader ;).
I have two unrelated observations:
1) Not sure if you meant it as an example or not, but you've initialized dictionary with empty strings. You'll have to remove those in the future unless you want an empty strings entry. You're better off initializing an empty dictionary with the correct types:
var dictionary = [String:[String]]()
2) You don't need to use self. to access an instance variable. Your code is simple enough that it's very obvious what the scope of dictionary is (see this great writeup on self from a Programmers's stack exchange post.
Copy this in your Playground, might help you understand the Dictionaries better:
import UIKit
var str = "Hello, playground"
struct DrugsLibrary {
var drugName = ""
var drugCategory = ""
var drugSubCategory = ""
}
var drugList = [DrugsLibrary]()
//This is the dictionary i'm trying to build:
var dictionary = ["":""]
func createDrugsList() {
var drug1 = DrugsLibrary()
drug1.drugName = "drug1"
drug1.drugCategory = "Antibiotics"
drug1.drugSubCategory = "Penicillins"
drugList.append(drug1)
var drug2 = DrugsLibrary()
drug2.drugName = "drug2"
drug2.drugCategory = "Antibiotics"
drug2.drugSubCategory = "Penicillins"
drugList.append(drug2)
var drug3 = DrugsLibrary()
drug3.drugName = "drug2"
drug3.drugCategory = "Antibiotics"
drug3.drugSubCategory = "Macrolides"
drugList.append(drug3)
}
createDrugsList()
print(drugList)
func addItemsToDict() {
for i in drugList {
dictionary["item \(i.drugSubCategory)"] = "\(i.drugName)"
}
}
addItemsToDict()
print(dictionary)