How do I fetch name from an object? - swift

let temp = printer.information?.reserved["accessory"];
print(temp)
Output:
Optional(Optional(<EAAccessory: 0x281d04db0> {
connected:YES
connectionID:40870953
name: TSP100
manufacturer: Star Micronics
modelNumber: TTRDFGIBI GY
serialNumber: 07657643f
ppid: (null)
regioncode: (null)
firmwareRevisionActive: 1.0.0
firmwareRevisionPending: (null)
hardwareRevision: 1.0.0
dockType:
certSerial: 15 bytes
certData: 908 bytes
protocols: (
"jp.star-m.starpro"
)
delegate: (null)
}))
The type of the above printed object is Any.
Not sure how to get the value of name from the above object.

Since you are getting an EAAAccessory object you can access the name property. Something like this:
if let accessory = printer.information?.reserved["accessory"] as? EAAAccessory {
let name = accessory.name
print(name)
} else {
print("Unable to access accessory")
}

Related

Append model to array in Swift only printing last item added

Im not sure what I am missing here, but it "looks" right to me.
I have the following two variables at the top of my view controller:
var itemSpecifics: ItemSpecifics!
var itemSpecificsArray = [ItemSpecifics]()
I make a call into a API and do the following when its successful:
self.itemSpecifics = ItemSpecifics()
self.itemSpecificsArray.removeAll()
Here is the area where I am getting information and adding it into itemSpecifics.
if let getItemSpecifics = item["ItemSpecifics"] as? NSDictionary {
if let getNameValueList = getItemSpecifics["NameValueList"] as? NSArray {
print("game value list count \(getNameValueList.count)")
for i in 0..<getNameValueList.count {
if let getName = getNameValueList[i] as? NSDictionary {
if let itemName = getName["Name"] as? String {
print(itemName)
self.itemSpecifics._itemSpecificName = itemName
}
if let getValue = getName["Value"] as? NSArray {
let itemValue = getValue[0] as? String
self.itemSpecifics._itemSpecificValue = itemValue!
print("-- \(itemValue!)")
}
}
//End The Condition Information
self.itemSpecificsArray.append(self.itemSpecifics)
}
}
}
So, its being printed correctly.
Professionally Graded
-- Not Graded
Sport
-- Baseball-MLB
Product
-- Lot
Player
-- Derek Jeter
Team
-- New York Yankees
Card Manufacturer
-- Topps
League
-- Major Leagues
Era
-- Modern (1981-Now)
Original/Reprint
-- Original
However, when I do this:
for i in 0..<self.itemSpecificsArray.count {
print(self.itemSpecificsArray[i].itemSpecificName)
print("** \(self.itemSpecificsArray[i].itemSpecificValue)")
}
It prints the following:
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Original/Reprint
** Original
Here is my class for ItemSpecifics.
class ItemSpecifics {
var _itemSpecificName: String!
var _itemSpecificValue: String!
var itemSpecificName : String {
if _itemSpecificName == nil {
_itemSpecificName = ""
}
return _itemSpecificName
}
var itemSpecificValue : String {
if _itemSpecificValue == nil {
_itemSpecificValue = ""
}
return _itemSpecificValue
}
}
What have I missed?
You only have a single instance of ItemSpecifics - you keep updating the properties of that one instance and adding it to the array, so in the end your array holds multiple references to the one instance and that one instance has the last values you assigned.
You can make your code much more "Swifty" - Use a struct rather than a class, which gives immutability; You shouldn't generally use that form of "_" private properties; you can just make a property read-only, but with a struct you won't need to any way.
Also, don't use NS... foundation classes in Swift unless it is unavoidable.
struct ItemSpecifics {
let name: String
let value: String
}
if let getItemSpecifics = item["ItemSpecifics"] as? [String:Any],
let getNameValueList = getItemSpecifics["NameValueList"] as? [[String:Any]] {
for nameValueList in getNameValueList {
if let name = nameValueList["Name"] as? String,
let value = nameValueList["Value"] as? String {
let newItem = ItemSpecifics(name: name, value: value)
self.itemSpecificsArray.append(newItem)
}
}
}

Swift guard else called on dictionary key with NULL value

If I have a Dictionary returned from a NSNotification containing the following
print(notificationObj.object)
Optional({
age = "<null>";
names = (
David
);
})
Then the guard else is called when trying to assign this to a variable:
guard let categories = notificationObj.object as? [String:[String]] else {
// Gets to here
return
}
How can I handle the case where a Dictionary key is null.
Your dictionary does contain ...
Optional({
age = "<null>";
names = (
David
);
})
... and ...
age = ... is String = String (value is single String),
names = ( ... ) is String = [String] (value is array of Strings).
You can't cast it to [String:[String]] because the first pair doesn't fit this type. This is the reason why your guard statement hits else.
Hard to answer your question. Dictionary contains names, you want categories, names key does contain David, which doesn't look like category, ... At least you know why guard hits else.
Your questions is not very clear.
However IF
You have a dictionary declared as follow [String:[String]]
And you want manage the scenario where a given key is not present
Like this
let devices : [String:[String]] = [
"Computers": ["iMac", "MacBook"],
"Phones": ["iPhone 6S", "iPhone 6S Plus"]
]
Then you can at least 2 solutions
1. conditional unwrapping
if let cars = devices["Car"] {
// you have an array of String containing cars here
} else {
print("Ops... no car found")
}
2. guard let
func foo() {
guard let cars = devices["Car"] else {
print("Ops... no car found")
return
}
// you have an array of String containing cars here...
cars.forEach { print($0) }
}
It appears that your printed notificationObject.object is constructed from a JSON string that looks like this:
"{ \"age\": null, \"names\":[\"David\"] }"
The reason that you are hitting your else clause is because age is actually a nil, and not a valid String array. I tried using [String: [String]?] and [String: NSArray?] neither of which seem to work. The type is actually an NSNull (which inherits from NSObject).
So you can cast to [String: AnyObject] and check for NSArray like this:
if let categories = j as? [String: AnyObject] where (categories["age"] is NSArray) {
print("age was array")
} else {
print("age is probably null")
}
You might be better off if your notification object simply omitted the "age" property when the value is null. Then you would be able to cast to [String: [String]].

Swift Variable Name

Is it possible to find out the variable name, what I called it, while the variable has a value?
SO what I mean is:
var varName: Int
...
if ((varName == "varName") && (varName == 6)) {
...
}
Is this possible?
take a look about Reflection in Swift example below
struct Car {
let type: CarType
let name: String
init(_ type: CarType, name: String) {
self.type = type
self.name = name
}
}
enum CarType {
case Sport
case Economics
}
let bmw = Car(CarType.Sport, name: "BMW")
let bmwMirror = Mirror(reflecting: bmw)
let children = bmwMirror.children
print("car properties: \(children.count)") //2
var generator = children.generate()
let type = generator.next()
print(type!.label) // type Optional
print(type!.value) //Sport
let name = generator.next()
print(name!.label) // name Optional
print(name!.value) //BMW
Note : I am using Swift 2.0 Xcode beta 7 in Swift 1.2 use let bmwMirror = reflect(bmw)
and you can access the properties bmwMirror.[indexOfProperty].1(.value or label)
Why you need to check variable name? Maybe better to use dictionary instead?
If you make variable names from string and then check it for right names, maybe better to check original strings?

Cast a NSManagedObject to it's class instance

I am getting stuck, and this makes me crazy. I have a function that returns a NSManagedObject:
let getaccount = AccountModel.getFirst(globals.managedObjectContext)
and I have to cast it into its generated representation Account
I'll do this:
dump("--------------------")
dump(getaccount)
dump("--------------------")
if let acc = getaccount as? Account {
print("OK")
} else {
print("not convertable ")
}
dump("*********************")
And the output FROM MY UNITTEST looks like this:
- --------------------
▿ Ticketstream.Account
▿ Some: Coredataexampleapp.Account #0
▿ super: <Coredataexampleapp.Account: 0x138d85f90> (entity: Account; id: 0x1398a9fe0 <x-coredata://06F96EF3-96A6-4C32-A6A2-F16BCB8318EA/Account/p1> ; data: {
active = 0;
avatar = (
);
config = (
);
createdAt = "2015-07-31 23:34:58 +0000";
displayName = "My Account (1)";
host = localhost;
lastUpdatedDate = "2015-07-31 23:34:58 +0000";
password = nil;
port = 8080;
schema = HTTPS;
username = "";
})
- NSObject: <Coredataexampleapp.Account: 0x138d85f90> (entity: Account; id: 0x1398a9fe0 <x-coredata://06F96EF3-96A6-4C32-A6A2-F16BCB8318EA/Account/p1> ; data: {
active = 0;
avatar = (
);
config = (
);
createdAt = "2015-07-31 23:34:58 +0000";
displayName = "My Account (1)";
host = localhost;
lastUpdatedDate = "2015-07-31 23:34:58 +0000";
password = nil;
port = 8080;
schema = HTTPS;
username = "";
})
- --------------------
not convertable
- *********************
How to cast a NSManagedObject into Account?
I need this, because I can't get the first Account otherwise than:
class func getFirst(context: NSManagedObjectContext) -> NSManagedObject? {
let request = NSFetchRequest(entityName: accountEntityName)
request.fetchLimit = 1
let list: NSArray = try! context.executeFetchRequest(request)
return list.firstObject as? NSManagedObject
}
I've tried this with NSManagedObject, AnyObject and Account... How do i get the first Account the right way?
UPDATE:
In normal running mode: all is fine! I'll get:
- --------------------
OK
- *********************
But not from my tests :-(
Thanks for your help, I am lost.
Select all your project files in turn and look at the File Inspector at right. Make sure all files have the 'Test' project checked in their Target Memberships.
There is no need to include all the normal class files in the test target. You just have to import the main module, and everything works as expected.
#testable import AppName
This is inserted automatically in Xcode 7 beta 4. For the casting issue see this answer.

Should a dictionary be converted to a class or struct in Swift?

I am working on a native iOS application that receives data in JSON format from a web-service which we are also in control of. The plan is to change out the backend database in a bout 18 months in favor of a different platform.
With that in mind, we want to be sure that that iOS app is going to be relatively easy to adapt to the new datasource, particularly as we may change the keys used in the associative array received from the server via JSON.
There are two goals:
Create a single location for each PHP request where the keys can be modified if needed. This would avoid digging through code to find things like job["jobNumber"].
Clean up our existing code to also eliminate references like job["jobNumber"].
We are both very new to Swift with no Objective-C experience, but I am was thinking a Struct or Class would be appropriate to create references like job.jobNumber.
Should a dictionary be converted into a class or struct? Sample code representing a reusable method of taking a Dictionary<String, String> as shown below and converting it to the recommended type would be extremely helpful.
Example Dictionary:
job = {
"jobNumber" : "1234",
"jobName" : "Awards Ceremony",
"client" : "ACME Productions"
}
Desired result:
println("job name is \(job.name)")
// prints: job name is Awards Ceremony
To access it like this you need to convert your dictionary to Struct as follow:
edit/update: Swift 3.x
struct Job: CustomStringConvertible {
let number: Int
let name, client: String
init(dictionary: [String: Any]) {
self.number = dictionary["jobNumber"] as? Int ?? 0
self.name = dictionary["jobName"] as? String ?? ""
self.client = dictionary["client"] as? String ?? ""
}
var description: String {
return "Job#: " + String(number) + " - name: " + name + " - client: " + client
}
}
let dict: [String: Any] = ["jobNumber": 1234,
"jobName" : "Awards Ceremony",
"client" : "ACME Productions"]
let job = Job(dictionary: dict)
print(job.number) // 1234
print(job.name) // "Awards Ceremony"
print(job.client) // "ACME Productions"
print(job) // "Job#: 1234 - name: Awards Ceremony - client: ACME Productions"""
edit/update:
Swift 4 or later you can use JSON Codable protocol:
struct Job {
let number: Int
let name, client: String
}
extension Job: Codable {
init(dictionary: [String: Any]) throws {
self = try JSONDecoder().decode(Job.self, from: JSONSerialization.data(withJSONObject: dictionary))
}
private enum CodingKeys: String, CodingKey {
case number = "jobNumber", name = "jobName", client
}
}
extension Job: CustomStringConvertible {
var description: String {
return "Job#: " + String(number) + " - name: " + name + " - client: " + client
}
}
let dict: [String: Any] = ["jobNumber": 1234,
"jobName" : "Awards Ceremony",
"client" : "ACME Productions"]
do {
let job = try Job(dictionary: dict)
print(job.number) // 1234
print(job.name) // "Awards Ceremony"
print(job.client) // "ACME Productions"
print(job) // "Job#: 1234 - name: Awards Ceremony - client: ACME Productions\n"
} catch {
print(error)
}
Definitely a job for a struct.
1. Structs are thread-safe and don't need to be managed by ARC.
2. Some studies have found them to be about 30,000x faster to work with than classes in general.
3. Structs also provide default initializers so your code will be cleaner.
4. In this case, you don't have to worry about inheritance/subclassing.
5. The Protocol Oriented Programming paradigm recommends using structs over classes if you're able.
struct Job {
let number: Int
let name: String
let client: String
}
Initializer for free:
let newJob = Job(number: 2, name: "Honey", client: "Jeff")
Or you can create a custom initializer that takes the dictionary:
struct Job {
let number: Int
let name: String
let client: String
init(json: [String: Any]) {
self.number = Int(dictionary["jobNumber"] as? String) ?? 0
self.name = dictionary["jobName"] as? String ?? ""
self.client = dictionary["client"] as? String ?? ""
}
}
usage:
let newJob = Job(json: yourDictionary)
print(newJob.number)
// outputs: 1234
You can add an extension to Dictionary like this to get generic objects:
extension Dictionary where Key == String, Value: Any {
func object<T: Decodable>() -> T? {
if let data = try? JSONSerialization.data(withJSONObject: self, options: []) {
return try? JSONDecoder().decode(T.self, from: data)
} else {
return nil
}
}
}
and use like this on any [String: Any] dictionaries:
let object: MyDecodableStruct? = dictionary.object()
I generally make use of value classes to achieve what you want to do. In my project I do something like following:
protocol Request : class {
func toDictionary() -> [String : String]
}
protocol Response : class {
init(dictionary: [String : String])
}
class MyRequest : Request {
var var1: Int
var var2: String
//Other stuff in class...
func toDictionary() -> [String : String] {
//Convert the value to dictionary and return
}
}
class MyResponse : Response {
var var1: String
var var2: Int
//You could have nested object as members
var innerObject: MyInnerResponseClass
//Other stuff in class...
var someCalculatedProperty: String {
return //Calculate property value
}
required init(dictionary: [String : String]) {
//Initialize class from dictionary
}
}
class MyInnerResponseClass: Response {
//Class definition here...
}
For objects that could be used as request and response you could implement both of the protocols.
You need to write code for translation once, but then it could be easy to use everywhere. Also by using calculated properties you may get extra ease.
I am not sure if you could just do it out of the box in Swift. I will require reflection which is not yet very well supported by Swift. Also even if there is reflection and you come up with clever way to use to achieve what you need, it could be quite slow if the data is quite large.
My two cents about "logic". )all correct about using structs and so on...)
Do NOT keep (as many from web do..) data in dict or JSON, convert it to struct always.
a lot of efficiently, think about for example about sorting in a tableview..