I am still new in the language swift. I do not come from the following after a day of searching.
After a segue I send the following data as an Any? object.
Optional(<Hond: 0x604000297cf0> (entity: Hond; id: 0xd000000000080000 <x-coredata://9C4A92D6-5E7D-4633-827E-0E2BB6F005CA/Hond/p2> ; data: {
chipnummer = 0;
dierenarts = "";
geboortedatum = "2015-11-28 08:56:33 +0000";
geslacht = 0;
gewicht = 0;
hondId = "30A102CB-E0A5-49F1-ABAA-6E73CA32AF43";
kleur = "";
naam = Ravi;
orderID = 1;
plaatsVanChip = "";
schofthoogte = 0;
telefoonnummerDierenarts = "";
vachttype = ""; }))
Now I think that I must treat the data as an optional, but that does not work at all. Now my question is how can I display the values such as name and date?
import UIKit
import CoreData
class hondDetialView: UIViewController {
var hond:Any?
override func viewDidLoad() {
super.viewDidLoad()
//print(hond as Any)
if let eenWaarde = hond {
print(eenWaarde)
}
// Do any additional setup after loading the view.
}
thank you for your help :)
Any is the worst choice.
It's the most unspecified type in Swift. It tells the compiler I-have-no-idea-what-it-is. And the compiler doesn't know that there are properties like naam and geboortedatum.
You know that the type is Hond, so declare the property
var hond: Hond?
even NSManagedObject would be much better than Any. Then you can write
if let eenWaarde = hond {
print(eenWaarde.naam)
}
If the segue sends always a Hond instance you can even declare the property as implicit unwrapped optional
var hond: Hond!
and omit the optional binding
print(hond.naam)
Related
My realm model class look like
class RoomRealmModel : Object {
dynamic var id: String = ""
var details = List<RoomDetailRealmModel>()
func saveItem() {
do {
let realm = try Realm()
realm.beginWrite()
realm.add(self, update: true)
try realm.commitWrite()
} catch{}
}
}
class RoomDetailRealmModel : Object{
dynamic var detailId: String = ""
dynamic var displayText: String = ""
}
I want to retrieve 'details' from the following.
details = RLMArray<RoomDetailRealmModel> <0x600000114f40> (
[0] RoomDetailRealmModel {
text = hello;
Counters = 9;
ParentID = ;
detailId = 33;
displayText = hello ;
}
);
I always get empty like in my console
(lldb) po (destinationData?[index]?.details)!
List<RoomDetailRealmModel> <0x600000853620> (
)
I am updating ‘details’ list via realm update command. I always get realm array.But I want to retrieve array type from realm array.Please help me, how to solve this issue
If you want to obtain [myObject] instead of List you can do something like this:
var array: [myObject] = [myObject]()
for object in myObjectList {
array.append(object)
}
Where myObjectList is List.
You can simply create a regular Swift Array from a Realm List by calling the initializer of Array accepting a Sequence, since List conforms to the sequence protocol.
So you can simply do
let room = RoomRealmModel()
let roomDetailsArray = Array(room.details)
Here's my doozy.
I've got this lovely little function in a file called functions.swift
//functions.swift
func latestActiveGoal() -> Object {
let realm = try! Realm()
let currentGoal = realm.objects(Goal).filter("Active == 1").sorted("CreatedOn").last
return currentGoal!
}
which returns a Goal object. (A Goal might be wanting to lose weight, or stop being so inept at Swift).
In a different view controller, I want to access this object. Here's what I'm trying:
//viewController.swift
#IBOutlet weak var aimText: UILabel!
let funky = functions()
func getGoals(){
var currentGoal = funky.latestActiveGoal()
print(currentGoal)
aimText.text = currentGoal.Title
}
The print(CurrentGoal) output shows this:
Goal {
id = 276;
Title = Goal Title;
Aim = Aim;
Action = Nothing;
Active = 1;
CreatedOn = 2016-02-12 00:14:45 +0000;
}
aimText.text = currentGoal.Title and aimText = currentGoal.Title both throw the error:
Value of 'Object' has no member 'Title'
By printing the contents of the object, I can see the data, but can't figure out how. Any help greatly appreciated.
As the error message said, currentGoal is a value of Object type which doesn't have member Title.
This is because function latestActiveGoal returns Object instead of Goal. You just need to make it return Goal by change the return type:
func latestActiveGoal() -> Goal {
Just replace your functions with below code.
It will works perfect.
This fuction will check if goal available, then only it will return.
func latestActiveGoal() -> Object? {
let realm = try! Realm()
let currentGoals = realm.objects(Goal).filter("Active == 1").sorted("CreatedOn")
if currentGoals.count > 0 {
return currentGoals.last;
}
return nil;
}
Your getGoals method will be as follow.
func getGoals(){
if let currentGoalObject = funky.latestActiveGoal() {
print(currentGoalObject)
let goal = currentGoalObject as! Goal
print(goal.Title)
aimText.text = goal.Title
}
}
In my Swift class I have the following:
var detailItem: Task?
var cellData:[String:String] = [:]
/* prepareForSegue not called before */
if (detailItem == nil) {
self.cellData = ["id":"", "titolo":"", "oggetto":"", "check_mail":"", "progetto_nome":"", "assegnato_a":"", "richiesto_da":"", "priorita":"", "termine_consegna":"", "stato":"Aperto"]
}
/* prepare for segue has been called */
else {
self.cellData["id"] = String(stringInterpolationSegment: self.detailItem!.id)
self.cellData["titolo"] = self.detailItem!.titolo
self.cellData["oggetto"] = self.detailItem!.oggetto
if (self.detailItem!.check_mail) {
self.cellData["check_mail"] = "true"
}
else {
self.cellData["check_mail"] = "false"
}
self.cellData["progetto_nome"] = self.detailItem!.progetto_nome
self.cellData["assegnato_a"] = self.detailItem!.assegnato_a
self.cellData["richiesto_da"] = self.detailItem!.richiesto_da
self.cellData["priorita"] = self.detailItem!.priorita
self.dateFormatter.dateFormat = "yyyy-MM-dd"
self.cellData["termine_consegna"] = self.dateFormatter.stringFromDate(self.detailItem!.termine_consegna)
self.cellData["stato"] = self.detailItem!.stato
var editButton:UIBarButtonItem = UIBarButtonItem(title: "Modifica", style: UIBarButtonItemStyle.Plain, target: self, action: "switchMode:")
self.navigationItem.rightBarButtonItem = editButton
}
where some properties of the Task class are optionals (like the id) and so they may be nil.
When I need to perform a task update operation I need to retrieve the data from cellData, create a task object and use it to update the database which requires an id. So this is what I do:
var taskToUpdate = Task(id: self.cellData["id"]!.toInt(),
...)
The problem is that id is always set to nil. I have tried:
println(self.cellData["id"]!.toInt())
and what I get is this:
Optional("Optional(102)").
Which is the correct way to cast that into Int?
The function toInt() returns always an optional because there are only a few cases where strings can be converted to integers. If you can ensure that the value is never nil, unwrap it
println(self.cellData["id"]!.toInt()!)
otherwise use optional bindings
If let idInt = self.cellData["id"]!.toInt() { println(idInt) }
You have two problems there:
.toInt() returns an optional.
The id in self.detailItem!.id is probably an optional, too.
The result is that an optional id with value 102 is converted to "Optional(102)" and not "102" as you would expect.
I would advise you a simple solution - don't use dictionaries to hold your data, use objects where properties have the correct types. Don't go around converting your numbers to strings and back. Otherwise you will have to put force unwraps everywhere, e.g.:
String(stringInterpolationSegment: self.detailItem!.id!)
I continued on my math question project, and it could now generate questions, so I need to try to use a global variable to use my answer's in generating the answer itself and putting the answer randomly into one of 4 choices. I decided to put a secret label outside of my view that shows the answer. Here's my code:
//important stuff
#IBOutlet var secretAnsarrrrr: UILabel!
//useless code
//declare the value of secretAnsarrrr
secretAnsarrrrr.text = String(answer)
numA.text = String(Int(randomNumber))
numB.text = String(Int(randomNumber2))
}
generateQuestion()
}
var optionAnswer:UInt32 = arc4random_uniform(4)
#IBAction func answerA(sender: UIButton) {
var otherAns:String = String(secretAnsarrrrr) //error
if optionAnswer == 0 {
optionA.text = secretAnsarrrrr.text
}
Doing so gives me the error of 'Missing argument label: StringInterpolationSegment in call'. It tells me to place it behind 'secretAnsarrrrr' in the parentheses. What does stringInterpolationSegment do and how do I fix this?
secretAnsarrrrr is not a string itself - it is a UILabel which also contains information like color and font. You need to tell Swift to use its text property:
var otherAns:String = String(secretAnsarrrrr.text)
I just encountered this error, and after some head scratching, I realised that I needed to unwrap an optional integer which I was trying to parse with String(...). As soon as I added the exclamation mark, the problem was solved:
var num: Int? = 1
var str = String(num!)
it is Better to write:
var num: Int? = 1
var str = num.map { String($0) } // if num == nil then str = nil else str = string representation
Inside the optional binding when I assign the variable ammo (and ammo2) I am pretty sure that I should be using ! to unbox the optional, but on my first attempt I put ? by mistake and was a little confused why it still worked, can anyone cast some light onto whats going on there?
let soldierA = Soldier(name: "Brian")
soldierA.weapon = Weapon()
soldierA.weapon!.grenadeLauncher = GrenadeLauncher()
let soldierB = Soldier(name: "Gavin")
soldierB.weapon = Weapon()
let soldierC = Soldier(name: "Berty")
soldierC.weapon = Weapon()
soldierC.weapon!.grenadeLauncher = GrenadeLauncher()
soldierC.weapon!.grenadeLauncher!.ammo = 234
let missionTeam = [soldierA, soldierB, soldierC]
for eachSoldier in missionTeam {
if let launcherAvailable = eachSoldier.weapon?.grenadeLauncher? {
var ammo = eachSoldier.weapon!.grenadeLauncher!.ammo // PRETTY SURE THIS IS RIGHT
var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo // SHOULD THIS WORK, IT DOES?
println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo)")
} else {
println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
}
}
.
// CLASSES
class Soldier {
var name: String
var weapon: Weapon?
init(name: String) {
self.name = name
}
}
class Weapon {
var ammo = 500
var grenadeLauncher: GrenadeLauncher?
}
class GrenadeLauncher {
var ammo = 20
}
EDIT
Thank you, I was getting confused about how this works, but I now see what is happening. Here is the modified eachSoldier section again, using optional binding with optional chaining...
for eachSoldier in missionTeam {
if let weapon = eachSoldier.weapon? {
if let launcher = eachSoldier.weapon?.grenadeLauncher? {
println("SOLDIER: \(eachSoldier.name) Weapon has launcher with \(launcher.ammo) ammo")
} else {
println("SOLDIER: \(eachSoldier.name) Weapon does not have launcher ")
}
} else {
println("SOLDIER: \(eachSoldier.name) does not have weapon ")
}
}
soldierC.weapon = Weapon()
soldierC.weapon!.grenadeLauncher = GrenadeLauncher()
soldierC.weapon!.grenadeLauncher!.ammo = 234
it is correct in the current pattern.
var ammo = eachSoldier.weapon!.grenadeLauncher!.ammo
implicitly unwraps the weapon and its grenadeLauncher; it does not care of whether or not they have been inited before, therefore it could lead a direct crash if your code tries to unwrap when any of them is still a nil value.
var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo
tries to access the weapon and its grenadeLauncher; if the object does not exist, they will be left alone, therefore nothing happens but the ammo2 will be nil only, and application can proceed.
therefore your flow could be similar to that:
for eachSoldier in missionTeam {
var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo
if ammo2 != nil {
println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo2)")
} else {
println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
}
}
In addition to what #holex has stated, I would like to say that your case called Optional Chaining, in which if you use ? instead of ! on an optional variable (or constant), that means you are checking if the variable (or the constant) is not nil. In other words, it has a value.
The lovely thing about optional chaining is that you can apply it to many levels.
For example:
Let's say you have these two classes:
class Student{
var subjects: [Subject]?
}
class Subject{
var name: String?
}
and you created a variable:
var william = Student()
At any time, you can print the name of the first subject as this:
print(william.subjects?[0].name)
Notice that the result of that print statement is nil, while if you unwrapped it like this:
print(william.subjects![0].name)
You would get a run time error