I want to make a 3D Array with Realm and I use List to accomplish this.
This is the code for my RealmDatabase:
class Sensors : Object {
dynamic var type = ""
dynamic var name = ""
let buttonAr = List<buttons>()
}
class buttons: Object{
let buttonsAdded = List<objectNameTopic>()
}
class objectNameTopic: Object {
dynamic var name = ""
dynamic var topic = ""
}
And this is what I use to call it:
var saving = Sensors()
var saving2 = objectNameTopic()
var but = buttons()
var array = ["on", "off"]
var array2 = ["1","2"]
var allSensors = useOfRealm.objects(Sensors.self)
override func viewDidLoad() {
super.viewDidLoad()
addSensor()
for i in 0...array.count-1 {
addSensor2(name: array[i], topic: array2[i])
}
if allSensors.count > 0 {
print(allSensors)
}
}
func addSensor() {
try! useOfRealm.write {
saving.type = "topic1"
saving.name = "mike"
useOfRealm.add(saving)
}
}
func addSensor2(name: String, topic: String) {
try! useOfRealm.write {
saving2.name = name
saving2.topic = topic
useOfRealm.add(saving2)
but.buttonsAdded.append(saving2)
saving.buttonAr.append(but)
}
}
This is what I get when I print the results:
Results<Sensors> (
[0] Sensors {
type = topic1;
name = mike;
buttonAr = RLMArray <0x6100000fd900> (
[0] buttons {
buttonsAdded = RLMArray <0x6100000fdb00> (
[0] <Maximum depth exceeded>,
[1] <Maximum depth exceeded>
);
},
[1] buttons {
buttonsAdded = RLMArray <0x6180000fd180> (
[0] <Maximum depth exceeded>,
[1] <Maximum depth exceeded>
);
}
);
}
)
Any Ideas of what I'm missing?
Thanks in advance
If the <Maximum depth exceeded> in the XCode console output is what you fear, fear no more. It's just a way the console is telling you that the object hierarchy is too deep for showing it to you, but the object(s) are there accessible through code.
Just try to print the content of your result by iterating through it and printing each child object instead of printing only the root.
Related
Sorry, I have a question about sort data.
I don't know how to sort each characters , I just sort by first characters like following image.
How can I sort characters in each section array.
Thanks.
var cityCollation: UILocalizedIndexedCollation? = nil
var sectionsCityArray = [[City]]()
var cityArray:[City] = [City]() //cityArray is my original data that is not sorting
func configureSectionCity() {
cityCollation = UILocalizedIndexedCollation.current()
let sectionTitlesCount = cityCollation!.sectionTitles.count
var newSectionsArray = [[City]]()
for _ in 0..<sectionTitlesCount {
let array = [City]()
newSectionsArray.append(array)
}
for bean in cityArray {
let sectionNumber = cityCollation?.section(for: bean, collationStringSelector: #selector(getter: City.name))
var sectionBeans = newSectionsArray[sectionNumber!]
sectionBeans.append(bean)
newSectionsArray[sectionNumber!] = sectionBeans
}
sectionsCityArray = newSectionsArray
}
Assuming the City object has a name property and you want the order q001, q002, q004, q005, q010, q012 you could use
newSectionsArray[sectionNumber!] = sectionBeans.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending }
localizedStandardCompare requires the Foundation framework
I have created in my application to the database using Realmsvift. Here is the output in the console. Please tell me, how do I read data from it in the application? For example, I want to display key-values: Oslo - 2.89. Thanks for the help.
class ViewController: UIViewController {
var city_list: [String] = ["Moscow", "London", "Oslo", "Paris"]
let realm = try! Realm()
override func viewDidLoad() {
super.viewDidLoad()
let manager: ManagerData = ManagerData()
for name in city_list {
manager.loadJSON(city: name)
}
let localWeather = realm.objects(WeatherData.self)
print(localWeather)
/////////////////////////////////////////
Results<WeatherData> (
[0] WeatherData {
city_name = Moscow;
tempList = RLMArray <0x6080002e2b00> (
[0] Temp {
temp = -4.25;
}
);
},
[1] WeatherData {
city_name = London;
tempList = RLMArray <0x6000002e4700> (
[0] Temp {
temp = 9.630000000000001;
}
);
},
[2] WeatherData {
city_name = Paris;
tempList = RLMArray <0x6000002e4800> (
[0] Temp {
temp = 6.59;
}
);
},
[3] WeatherData {
city_name = Oslo;
tempList = RLMArray <0x6000002e4900> (
[0] Temp {
temp = -2.89;
}
);
}
If I understand your question correctly, you want to get properties from each model.
If that is the case, you're almost there. localWeather is like an array in the Realm's world (e.g., type of Results<WeatherData>).
You can just access it like normal swift's array/objects:
let firstWeather = localWeather[0]
let name = firstWeather.city_name
let temp = firstWeather.tempList[0].temp
// do what you want with 'name' and 'temp', e.g. key-value
print("\(name) - \(temp)")
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 2 Realm Models:
class CourseModel: Object {
dynamic var coursename = ""
dynamic var par3field = 0
dynamic var par4field = 0
dynamic var par5field = 0
let scoreModels: List<ScoresModel> = List<ScoresModel>()
override internal static func primaryKey() -> String? { return "coursename" }
}
class ScoresModel: Object {
dynamic var dateplayed = ""
var courseModel: CourseModel? {
return linkingObjects(CourseModel.self, forProperty: "scoreModels").first
}
}
The app user will first add a new course for which I use CourseModel. As the user plays a course they enter scores for that course, for which I use ScoresModel, hence the primary key 'coursename'.
I query the CourseModel with
let realm = try Realm()
let results = realm.objects(CourseModel)
return results
and it produces the following result
Results<CourseModel> (
[0] CourseModel {
coursename = First Course;
par3field = 4;
par4field = 10;
par5field = 4;
scoreModels = RLMArray <0x797a36d0> (
[0] ScoresModel {
dateplayed = Apr 5, 2016; },
[1] ScoresModel {
dateplayed = Mar 3, 2016; }
);
},
[1] CourseModel {
coursename = Second Course;
par3field = 4;
par4field = 10;
par5field = 4;
scoreModels = RLMArray <0x7a046f40> (
[0] ScoresModel {
dateplayed = Apr 5, 2016; }
);
}
)
The ScoresModel produces a similar result but without the CourseModel data.
The ScoresModel has a lot of data in it, I only showed 'dateplayed' here to keep it short.
My question is this; when I've extracted the data from Realm how can I access a particular field to work with that data, i.e. how do I get the par5field data to do calculations with it, and also the 2nd question how do I get to the scoreModels data, for example 'dateplayed' to list the dates in a table for example?
When you perform a query against Realm, the results are returned in a Results object that behaves exactly like an array. So you need to iterate through each object to access the properties you want for each one.
To answer your first question, to access the par5field property (From just the first object):
let firstObject? = results.first
let par5field = firstObject.par5field
// Do calculations with it
For your second question, scoreModels is just a standard array object, so you can just insert the values it into a table view as you would a standard Array object.
If you wanted to list ALL of the ScoreModel objects, regardless of which CourseModel objects they belong to, you can perform a Realm query to get them directly.
let realm = try! Realm()
let results = realm.objects(ScoreModel)
return results
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)