Swift Struct unable to set array elements above 0 - ios

I have following Swift struct:
struct MainStruct : Decodable{
var array : [InternalArray]?
}
struct InternalArray : Decodable{
var firstName : String?
var lastName : String?
var Number : Int?
}
And this is how I'm using it:
var testing: MainStruct? = MainStruct()
testing?.array = []
testing?.array!.append(InternalArray())
testing?.array![0].firstName = "TEST"
testing?.array![1].firstName = "TEST 1" - error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION
It seems to work fine when I'm setting array element [0] but when I try to set element [1] I get an error. Maybe somebody know what is wrong with my implementation ?

The problem is you only have 1 item (index 0).
Let's unpack this, first we unwrap your option MainStruct in the testing variable, and unwrap the optional array:
if let unwrappedTestingMainStruct = testing,
let unwrappedArray = unwrappedTestingMainStruct.array {
unwrappedArray.count // = 1
}
You then try to access testing?.array![1] which would be the second item in the array… which doesn't exist.
If you just had the line:
testing?.array![1]
you would see the same error

Related

Access Value in Dictionary using Random Number

I am trying to access the value from a dictionary using a random number, but I am lost, can someone please guide?
Here is what I have:
var themes = ["Halloween": "πŸ˜ˆπŸ’€πŸ€‘πŸ‘»πŸ€–πŸ‘½", "Sports": "πŸ‰πŸ“β›³οΈβš½οΈπŸŽ³πŸŽ±" , "Faces": "πŸ˜€πŸ˜πŸ˜¨πŸ€—πŸ˜€πŸ€€", "Animal": "πŸ¦“πŸ˜ΌπŸ˜ΊπŸ˜ΏπŸ™€πŸ™ˆ"]
// This Does not work for some reason?
lazy var themeRandomNumber = themes.count.arc4random
lazy var currentTheme = themes[themeRandomNumber]
//Cannot subscript a value of type[String : String]' with an index of type 'Int'
This makes sense since, I am trying to access the key using an Int when it is obviously a String, but not sure how to proceed?
lazy var currentEmoji = themes[currentTheme]
extension Int{
var arc4random: Int{
if self > 0 {
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
return -Int(arc4random_uniform(UInt32(abs(self))))
} else {
return 0
}
}
}
Just replace
lazy var currentEmoji = themes[currentTheme]
with
var currentTheme = themes.randomElement()
print(currentTheme?.value) //Optional("πŸ‰πŸ“β›³οΈβš½οΈπŸŽ³πŸŽ±")
print(currentTheme?.key) //Optional("Sports")
Here randomElement is new property which you can use to get random element.
Because you're not accessing the key of your dictionary, you need to select "Halloween", "Sports", "Faces" or "Animal" - your themes dict's keys.
You can use some custom mapping method with Int.random(in: 0...3) or a Keys enum conforming to CaseIterable, and then you need to select a random character (emoji) in the String for your given Key (via a random number in the range 0..<string.length).
EDIT
With Swift 4.2+ (Xcode 10) you can use randomElement():
var themes = ["Halloween": "πŸ˜ˆπŸ’€πŸ€‘πŸ‘»πŸ€–πŸ‘½", "Sports": "πŸ‰πŸ“β›³οΈβš½οΈπŸŽ³πŸŽ±" , "Faces": "πŸ˜€πŸ˜πŸ˜¨πŸ€—πŸ˜€πŸ€€", "Animal": "πŸ¦“πŸ˜ΌπŸ˜ΊπŸ˜ΏπŸ™€πŸ™ˆ"]
var randomEmoji = themes.randomElement()?.value.randomElement()

App crashes when I am trying to saved data in my model

I am developing an App using Realm. At some point in my app when I try to manipulate my model, my app crashed in an unexpected way. Here is what the stack trace said
Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first
What I am trying to do :
lets break down my problem in parts.following is my model of app
#objcMembers public class ClassGroup : Object , Codable {
dynamic var Id : Int? = ""
dynamic var ClassName : String? = ""
dynamic var TeacherId : Int = 0
dynamic var Teachers : [TeacherMdoel]? = []
}
#objcMembers public class TeacherModel : Object , Codable {
dynamic var Id : String? = ""
dynamic var Name : String? = ""
dynamic var ClassId : Int = 0
dynamic var Students : [StudentClass]? = []
}
#objcMembers public class StudentModel : Object , Codable {
dynamic var Id : String? = ""
dynamic var Name : String? = ""
dynamic var ClassId : Int = 0
dynamic var TeacherId : Int = 0
}
now I am trying to get the list of all classes like this from realm (after saving them to realm )
let mClassLists = mDbHelper.realmObj.objects(ClassGroup.self)
Now here I get exception/error. What I am doing is, I am trying to populate my UITableView with some data that consist of all of the above models. I am fetching data and saving them in my model and trying to supply that list to UITableView but my app crash with the error I mentioned above
let mClassLists = mDbHelper.realmObj.objects(ClassGroup.self)
let classLists = Array (mClassLists)
for classModel in classLists {
let resultPredicateTeachers = NSPredicate(format: "ClassId == %#", classModel.Id)
let mTeachersList = mDbHelper.realmObj.objects(TeacherModel.self).filter(resultPredicateTeachers)
if(mTeachersList.count > 0){
var listTeachers : [TeacherModel] = []
for teacherModel in mTeachersList {
let resultPredicateStudent = NSPredicate(format: "TeacherId == 29")
let mStudentList = mDbHelper.realmObj.objects(StudentModel.self).filter(resultPredicateStudent)
if(mStudentList.count > 0){
let studentsList = Array(mStudentList)
teacherModel.Students = studentsList[0]
}
listTeachers.append(savedDetailItem)
}
classModel.Teachers? = (listTeachers)
listClassModel.append(classModel)
}
}
**In the Above code you can see that I am gathering data on behalf of Ids and saving the resultant arrays in the model. So I am getting error in the following line
**
teacherModel.Students = studentsList[0]
now I really do not understand why it is happening? I am not saving data in realm, I am saving in my model, still I am getting error.
In Realm database, if you want to modify any model (save new data or update), the operation should be performed in a write transaction:
try! realm.write {
realm.add(<your_model_objects>)
}

Check if an element is present in 3D array Swift

I have an array which gets instantiated in viewDidLoad like var bookingsArray : [[String]] = []
I am adding elements to it in this way:
var configuration: [String] = []
configuration.append(textfieldFacility.text!)
configuration.append((pickSlotTF.text?.components(separatedBy: " ")[0])!)
configuration.append((pickSlotTF.text?.components(separatedBy: " ")[1])!)
bookingsArray.append(configuration as [String])
bookingsArray looks like :
[["A", "20-08-2017", "14:00"], ["B", "20-08-2017", "14:00"]]
While adding new elements to bookingsArray, I want to check if the new element is already present in the array. How do I do it in this case of multi-dimensional array?
First of all, if you want unique objects use a Set.
If this is not possible I highly recommend to use a custom struct which can conform to Equatable rather than a nested array , for example
struct Booking : Equatable {
let facilty : String
let date : String
let time : String
static func ==(lhs : Booking, rhs : Booking) -> Bool {
return lhs.facilty == rhs.facilty && lhs.date == rhs.date && lhs.time == rhs.time
}
}
Then declare the array as
var bookingsArray = [Booking]()
and create an object with
let dateArray = pickSlotTF.text!.components(separatedBy: " ")
let configuration = Booking(facility: textfieldFacility.text!,
date: dateArray[0],
time = dateArray[1])
bookingsArray.append(configuration)
The huge benefit is that you can easily check
if bookingsArray.contains(item)
You can simply search for it with contains().
var configuration: [String] = []
configuration.append(textfieldFacility.text!)
configuration.append((pickSlotTF.text?.components(separatedBy: " ")[0])!)
configuration.append((pickSlotTF.text?.components(separatedBy: " ")[1])!)
if !bookingsArray.contains(where: {$0 == configuration}) {
bookingsArray.append(configuration)
}

Error after converting to Swift 3.0

After I converted my project to Swift 3.0, I find error in log from variable:
var arrayOfHours = stringArray.map {String(describing: $0!.characters.prefix(2))}
Error is:
code of error: "Optional(Swift.String.CharacterView(_core: Swift._StringCore(_baseAddress: Optional(0x000060800024ee70), _countAndFlags: 2, _owner: Optional(Swift._HeapBufferStorage<Swift._StringBufferIVars,
Swift.UInt16>))))"
where is my error occuring?
Update:
var stringArray in console: [Optional("1226"), Optional("1249"), Optional("1312"), Optional("1336"), Optional("1359"), Optional("1422"), Optional("1446"), Optional("1509"), Optional("1532"), Optional("1549"), Optional("1607"), Optional("1624"), Optional("1642"), Optional("1659"), Optional("1717"), Optional("1734"), Optional("1752"), Optional("1809"), Optional("1827"), Optional("1844"), Optional("1902"), Optional("1919"), Optional("1954"), Optional("2032"), Optional("2107"), Optional("2142"), Optional("2217"), Optional("2252"), Optional("2327"), Optional("2402"), Optional("2437"), Optional("2512")]
var stringArray: [String?] = ["1226", "1249"]
print(stringArray) // [Optional("1226"), Optional("1249")]
var arrayOfHours = stringArray.map { String($0!.characters.prefix(2)) }
print(arrayOfHours) // ["12", "12"]
Well its giving you an Optional of the String casting because String() will return nil if it found something else rather than a String, So what you'll have to do is unwrap that as in :
stringArray.map {String(describing: $0!.characters.prefix(2))!}
Just added an force unwrap ! to the String() result

How to Deal with Default Initializer when variable are not initialized Using Struct

I'm using swift struct and trying to use its default initializer when my struct variables are not initialize, I try both non-optional and optional variables but in its only showing "memberwise Initializer".
below is example with optional variables
struct myFirstStruct {
var value1:String?
var value2:String?
}
below is example with non-optional variables
struct myFirstStruct {
var value1:String
var value2:String
}
and it only gives
myFirstStruct(value1: <#String?#>, value2: <#String?#>)
and i want to use myFirstStruct()
help me. :)
Xcode is only showing you the 'member-wise' initialiser, but it's perfectly valid to use myFirstStruct(), passing no arguments, because all your variables have default values.
struct myFirstStruct {
var value1:String?
var value2:String = "InitialString"
}
let s1 = myFirstStruct()
// value1 = nil, value2 = "InitialString"
let s2 = myFirstStruct(value1: "Hello", value2: "World")
// value1 = "Hello", value2 = "World"
Need to set default value.
struct myFirstStruct {
var value1:String? = nil
var value2:String? = nil
}
let object = myFirstStruct()

Resources