Xcode Error "Expected '{' in body of function declaration" - swift

I have tried everything and I cannot figure out the error.
import Foundation
import Firebase
struct User {
var email: String!
var firstname: String
var lastname: String
var uid: String!
var profilePictureUrl: String
var country: String
var ref: FIRDatabaseReference!
var key: String = ""
init(email: String, firstname: String, lastname: String, uid: String, profilePictureUrl: String, country: String) {
self.email = email
self.firstname = firstname
self.lastname = lastname
self.profilePictureUrl = profilePictureUrl
self.country = country
self.ref = FIRDatabase.database().reference()
}
func toAnyObject() -> [String: Any] {
return ["email": email, "firstname": firstname, "lastname": lastname, "country": country, "uid": uid, "profilePictureUrl": profilePictureUrl]
}
}
The error is in the function toAnyObject.

Your function return [String : Any]. However, Its value is not Any.It is possible to edit temporarily as easy to understand as follows.
func toAnyObject() -> [String: Any] {
return ["email": email, "firstname": firstname, "lastname": lastname, "country": country, "uid": uid, "profilePictureUrl": profilePictureUrl] as [String : Any]
Hope it can help you fix issuse.

Related

Serialize json for its sample as a string

i'm trying to serialize a json but i have an error could someone give me a guide please i'm doing wrong i'm new to swift[enter image description here][1]
let code = "00001"
let firstName = "Joe"
let lastName = "Doe"
let middleName = "Mc."
let age = 100
let weight = 45
let jsonObject: [String: [String:Any]] = [
"code": code, <---- Cannot convert value of type 'String' to expected dictionary value type '[String : Any]'
"attributeMap": [
"first_name": firstName,
"middle_name": middleName,
"last_name": lastName,
"age": age,
"weight": weight
]
]
if let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted),
let str = String(data: data, encoding: .utf8) {
print("===> \(str)")
}
--I would like a result like this JSON format
{
"code": "00001",
"attributeMap": {
"first_name": "Joe",
"middle_name": "Mc",
"last_name": "Doe",
"age": "23",
"weight": "home.zul"
}
}
If it repeatable operation I will prefer to use more "swifty" way. Let's define two structs
Person
struct Person: Encodable {
// Keys
enum CodingKeys: String, CodingKey {
case firstName = "first_name"
case middleName = "middle_name"
case lastName = "last_name"
case age
case weight
}
// Properties
let firstName: String
let middleName: String
let lastName: String
let age: Int
let weight: Double
}
The next one
Entity
struct Entity: Encodable {
// Keys
enum CodingKeys: String, CodingKey {
case code
case person = "attributeMap"
}
// Properties
let code: String
let person: Person
}
Usage
let person = Person(
firstName: "Joe",
middleName: "Mc.",
lastName: "Doe",
age: 100,
weight: 45
)
let entity = Entity(
code: "200",
person: person
)
if
let data = try? JSONEncoder().encode(entity),
let json = String(data: data, encoding: .utf8)
{
// Do something
}
Result
{"attributeMap":{"age":100,"last_name":"Doe","middle_name":"Mc.","weight":45,"first_name":"Joe"},"code":"200"}

CompactMapValues not working on this simple dictionary

I have a model that looks like:
public struct Profile {
public let bio: String?
public let company: String
public let createdDate: Date
public let department: String
public let email: String
public let firstName: String
public let coverImageURL: URL?
public let jobTitle: String
public let lastName: String
public let location: String?
public let name: String
public let profileImageURL: URL?
public let roles: [String]
public let isActive: Bool
public let updatedDate: Date?
public let userID: String
public init(
bio: String?, company: String, createdDate: Date, department: String, email: String, firstName: String, coverImageURL: URL?, jobTitle: String,
lastName: String, location: String?, name: String, profileImageURL: URL?, roles: [String], isActive: Bool, updatedDate: Date?, userID: String) {
self.bio = bio
self.company = company
self.createdDate = createdDate
self.department = department
self.email = email
self.firstName = firstName
self.coverImageURL = coverImageURL
self.jobTitle = jobTitle
self.lastName = lastName
self.location = location
self.name = name
self.profileImageURL = profileImageURL
self.roles = roles
self.isActive = isActive
self.updatedDate = updatedDate
self.userID = userID
}
}
extension Profile: Equatable { }
I am trying to create a tuple that represents it as (model: Profile, json: [String: Any])
using the following method -
func makeProfile() -> (model: Profile, json: [String: Any]) {
let updatedDate = Date()
let updatedDateStr = updatedDate.toString(dateFormat: "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX")
let createdDate = Date()
let createdDateStr = createdDate.toString(dateFormat: "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX")
let coverImageURL = makeURL("https://headerUri.com")
let profileImageURL = makeURL("https://pictureUri.com")
let model = Profile(
bio: "Some Bio",
company: "Cool Job INC",
createdDate: createdDate,
department: "Engineering",
email: "name#domain.tld",
firstName: "Anne",
coverImageURL: coverImageURL,
jobTitle: "Test Dummy",
lastName: "Employee",
location: "London",
name: "Anne Employee",
profileImageURL: profileImageURL,
roles: ["ADMIN"],
isActive: true,
updatedDate: updatedDate,
userID: UUID().uuidString
)
let json: [String: Any] = [
"bio": model.bio,
"company": model.company,
"createdDate": createdDateStr,
"department": model.department,
"email": model.email,
"firstName": model.firstName,
"headerUri": model.coverImageURL?.absoluteString,
"jobTitle": model.jobTitle,
"lastName": model.lastName,
"location": model.location,
"name": model.name,
"pictureUri": model.profileImageURL?.absoluteString,
"roles": model.roles,
"isActive": model.isActive,
"updatedDate": updatedDateStr,
"userId": model.userID
].compactMapValues { $0 }
return (model: model, json: json)
}
}
extension Date {
func toString(dateFormat format: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: self)
}
}
All of the optional properties are showing a warning Expression implicitly coerced from 'String?' to 'Any'
I have added .compactMapValues { $0 } to the dict but has had no effect.
How can I clear this warning?
You're getting an error because you trying to implicitly coerce an optional value (which could be nil) to Any, which hides that the value could be nil.
compactMapValues doesn't guarantee at compile-time that the value is not nil; all the compiler knows is that something that is an optional (like String?) is now treated as a non-optional Any.
One way you could avoid the error is by providing a default value instead of the optional:
let json: [String: Any] = [
"bio": model.bio ?? ""
// ...
]
Alternatively, you can create a dictionary of: [String, Any?] to assign values to, and then use .compactMapValues, which would give you back non-optional values of Any.
let withOptionals: [String: Any?] = [
"bio": model.bio,
// ...
]
let json: [String, Any] = withOptionals.compactMapValues { $0 }
You're getting the warning because the values are optional when you initialize the dictionary. Your .compactMapValues { $0 } won't help because by then it's "too late".
Instead you could initialize an empty dictionary and add the values 1 by 1.
var json = [String: Any]()
json["bio"] = model.bio
json["company"] = model.company
// all of the other values
json["userId"] = model.userID

How to model a Swift dictionary property on a Realm object?

How should I model a dictionary property on a Realm object so when encoded to JSON I can get this:
{
"firstName": "John",
"lastName": "Doe",
"favoriteThings": {
"car": "Audi R8",
"fruit": "strawberries",
"tree": "Oak"
}
}
I tried creating a new Object FavoriteThings with 'key' and 'value' properties as I've seen elsewhere...
public class Person: Object {
#objc dynamic var firstName = ""
#objc dynamic var lastName = ""
var favoriteThings = List<FavoriteThings>()
}
But List gives me an array, naturally, when I encode it to JSON. I don't want an array. I'm using Swift Codable.
{
"firstName": "John",
"lastName": "Doe",
"favoriteThings": [
{
"key": "fruit",
"value": "strawberries"
},
{
"key": "tree",
"value": "Oak"
}
],
}
Any pointers appreciated!
Gonzalo
As you know, Lists are encoded into json arrays by default. So, to encode a List into a Dictionary you'll have to implement a custom encode method to do exactly that.
public class FavoriteThings: Object {
#objc dynamic var key = ""
#objc dynamic var value = ""
convenience init(key: String, value: String) {
self.init()
self.key = key
self.value = value
}
}
public class Person: Object, Encodable {
enum CodingKeys: String, CodingKey {
case firstName
case lastName
case favoriteThings
}
#objc dynamic var firstName = ""
#objc dynamic var lastName = ""
let favoriteThings = List<FavoriteThings>()
convenience init(firstName: String, lastName: String, favoriteThings: [FavoriteThings]) {
self.init()
self.firstName = firstName
self.lastName = lastName
self.favoriteThings.append(objectsIn: favoriteThings)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(firstName, forKey: .firstName)
try container.encode(lastName, forKey: .lastName)
var favThings: [String: String] = [:]
for thing in favoriteThings {
favThings[thing.key] = thing.value
}
try container.encode(favThings, forKey: .favoriteThings)
}
}
And the usage would be like this:
func testEncode() {
let john = Person(
firstName: "John",
lastName: "Doe",
favoriteThings: [
.init(key: "car", value: "Audi R8"),
.init(key: "fruit", value: "strawberries"),
.init(key: "tree", value: "Oak"),
])
let encoder = JSONEncoder()
let data = try! encoder.encode(john)
if let string = String(data: data, encoding: .utf8) {
print(string)
}
}
Which prints:
{"firstName":"John","favoriteThings":{"car":"Audi R8","fruit":"strawberries","tree":"Oak"},"lastName":"Doe"}

Swift: How to convert Array of Dictionary to structure?

I have:
array = [["name": String, "lastName": String],
["name": String, "lastName": String],
["name": String, "lastName": String]]
(a: [Сlass.[String:String]]) -> [Class.SomeStruct] {}
How to make a structure with its properties from this array?
Like this:
struct SomeStruct {
let name: String
let lastName: String
}
You can use map or compactMap to transform your dictionaries into structs.
let array = [["name": "String", "lastName": "String"],
["name": "String", "lastName": "String"],
["name": "String", "lastName": "String"]]
struct SomeStruct {
let name: String
let lastName: String
}
let values = array.compactMap { data -> SomeStruct? in
guard let name = data["name"], let lastName = data["lastName"] else {
return nil
}
return SomeStruct(name: name, lastName: lastName)
}
Note: The compactMap will silently ignore all dictionaries that doesn't contains a name or a lastName key.
Use Codable
// MARK: - SomeStructElement
struct SomeStructElement: Codable, Equatable {
let name: Int?
let lastName: String?
enum CodingKeys: String, CodingKey {
case name = "name"
case lastName = "lastName"
}
}
And then use JSONDecoder:
let someStructArray: Array<SomeStructElement> = try? JSONDecoder().decode(Array<SomeStructElement>.self, from: data) ?? []
Source: Encoding and Decoding Custom Types (Apple developer)

how can I construct the alamofire query based on array entries in Swift?

I have a class SingleUser:
class SingleUser: NSObject, NSCoding {
var username: String
var display_name: String
var facebook_username: String
var device_id: String
.
.
.
}
and I have an array of those users:
let blockedUsers: [SingleUser] = NSKeyedUnarchiver.unarchiveObject(with:
(defaults.object(forKey: "myUsers") as! Data)) as! [SingleUser]
I want to pass it with Alamofire to my webservice.
I have already some parameters defined:
var params = [
"long": lon as AnyObject,
"lat": lat as AnyObject,
"startDate": DateCalc.convertValueToDate(defaults.float(forKey: "startDate")) as AnyObject,
"endDate": DateCalc.convertValueToDate(defaults.float(forKey: "endDate")) as AnyObject
] as [String: AnyObject]
and now I want to append my users somehow, e.g. as:
"users" = {
{ "username" = "xxxx",
"display_name" = "xxxx",
"facebook_username" = "xxxx",
"device_id" = "xxxx"
},
{ "username" = "yyyy",
"display_name" = "yyyy",
"facebook_username" = "yyyy",
"device_id" = "yyyy"
},
.
.
.
}
Can you tell me how could I iterate over that array and append it to my params array?
class SingleUser: NSObject, NSCoding {
var username: String
var display_name: String
var facebook_username: String
var device_id: String
var jsonFormat: [String: AnyObject] {
return ["username": username,
"display_name": display_name,
"facebook_username": facebook_username,
"device_id": device_id]
}
}
And then:
var users = [[String: AnyObject]]()
blockedUsers.forEach { user in
users.append(user.jsonFormat)
}
params["users"] = users