Swift 3 Init Method That Accepts JSON with Optional Parameters

Swift 3 init method that accepts JSON with optional parameters

Besides my comment about the naming convention, there is no need to make your properties variable. You should take a look at the "??" nil coalescing operator:

class Address {
let id: Int
let addressType: Int
let addressStatus: Int
let address1: String
let address2: String
let city: String
let state: String
let zip: String
let country: String
let latitude: Double?
let longitude: Double?

init(id: Int, addressType: Int, addressStatus: Int, address1: String = "", address2: String = "", city: String = "", state: String = "", zip: String = "", country: String = "", latitude: Double? = nil, longitude: Double? = nil) {
self.id = id
self.addressType = addressStatus
self.addressStatus = addressStatus
self.address1 = address1
self.address2 = address2
self.city = city
self.state = state
self.zip = zip
self.country = country
self.latitude = latitude
self.longitude = longitude
}
init?(json: [String: Any]) {
guard
let id = json["Id"] as? Int,
let addressType = json["AddressType"] as? Int,
let addressStatus = json["AddressStatus"] as? Int,
let isDeleted = json["IsDeleted"] as? Bool
else {
return nil
}
self.id = id
self.addressType = addressType
self.addressStatus = addressStatus
self.address1 = json["Address1"] as? String ?? ""
self.address2 = json["Address2"] as? String ?? ""
self.city = json["City"] as? String ?? ""
self.state = json["State"] as? String ?? ""
self.zip = json["Zip"] as? String ?? ""
self.country = json["Country"] as? String ?? ""
self.latitude = json["Latitude"] as? Double
self.longitude = json["Longitude"] as? Double

print(isDeleted)
// call super.init here
}
}

let address1 = Address(id: 1, addressType: 2, addressStatus: 3)
let address2 = Address(id: 2, addressType: 3, addressStatus: 4, address1: "Any Address", latitude: 22.0, longitude: 43.0) // You don't need to add all parameters as long as you keep them in the same order as your initializer
print(address1.id) // 1
print(address1.address1) // "" empty String
print(address2.latitude ?? "nil") // 22.0
print(address2.longitude ?? "nil") // 43.0

Swift 3 optional parameters

I'm not sure why no one took the easy points on this answer, but the answer is to simply make your properties optionals, and then you can set them with a value, or nil. You can also create convenience initializers that automatically set certain values to nil if you want. So, using my app as an example, I have a model that gets built from an API call. that model has values like id, created_at, etc that don't exist until a record is saved to the server, but I create objects locally, store them, and eventually send them to the server, so I need to be able to set the above values only when creating an object from JSON, so here is what I did:

class Story: NSObject, NSCoding {
var id: Int?
var title, coverImageURL: String?
var coverImage: UIImage?

required init?(anId: Int?, aTitle: String?, aCoverImageURL: String?) {
self.id = anId
self.title = aTitle
self.coverImageURL = aCoverImageURL
}
convenience init?(json: [String: Any]) {
let id = json["id"] as? Int
let title = json["title"] as? String
let coverImageURL = json["cover_image"] as? String

self.init(
anId: id,
aTitle: title,
aCoverImageURL: coverImageURL,
)
}

convenience init?(aTitle: String, aCoverImage: UIImage?) {
let title = aTitle
let subtitle = aSubtitle
let coverImage = aCoverImage
let isActive = activeStatus

self.init(
anId: nil,
aTitle: title,
aCoverImageURL: nil,
aCoverImage: coverImage,
)
}

As you can see, I only set two of the values when I'm creating an object locally, and the other values are just set to nil. To allow a value to be set to nil, just make it an optional when setting it. Simple!

How to initialize class with optional properties in Swift 3

You need to define your class type for model

 class BaseEntity {

to

 class BaseEntity: NSObject {

This is the way you can create your model class: -

//Model Class
class BaseModel: NSObject {
var name: String
var address: String
var mobilenumber: Int

init(name: String?, address: String?, mobilenumber: Int?) {
self.name = name ?? ""
self.address = address ?? ""
self.mobilenumber = mobilenumber ?? 0
}
}

//Pass value inside model class
class ViewController: UIViewController {

var model = [BaseModel]() //Model Array Initialization here

override func viewDidLoad() {
super.viewDidLoad()

//Pass value inside Model
model.append(BaseModel(name: "Your name", address: "Your address", mobilenumber: 5545545452))

}
}

//Get value from Model class
class DetailsController: UIViewController {
var details: BaseModel?

override func viewDidLoad() {
super.viewDidLoad()
//Retrive value from model
let name = details?.name ?? ""
let address = details?.address ?? ""
let mobile = details?.mobilenumber ?? 0
}
}

How to insert into Sqlite with optional parameters using Swift 3

Make all your class properties constants (declare with let) and make them non optional adding a required init() with all your Address properties parameters. BTW it is Swift convention to start your vars naming with a lowercase letter. Note: You should use Int instead of Int64 unless it is a requirement. Regarding the optionality of your properties you can just assign a default value for them at initialization time. Btw It is better to use a struct unless you need to make your object persist (NSCoding compliant):

struct Address {
let id: Int
let addressType: Int
let addressStatus: Int
let address1: String
let address2: String
let city: String
let state: String
let zip: String
let country: String
let latitude: Double?
let longitude: Double?
init(id: Int, addressType: Int, addressStatus: Int, address1: String = "", address2: String = "", city: String = "", state: String = "", zip: String = "", country: String = "", latitude: Double = nil, longitude: Double = nil) {
self.id = id
self.addressType = addressStatus
self.addressStatus = addressStatus
self.address1 = address1
self.address2 = address2
self.city = city
self.state = state
self.zip = zip
self.country = country
self.latitude = latitude
self.longitude = longitude
}
}

So you can create your new object Address as follow:

let address1 = Address(id: 1, addressType: 2, addressStatus: 3)
let address2 = Address(id: 2, addressType: 3, addressStatus: 4, address1: "Any Address", latitude: 22.0, longitude: 43.0) // You don't need to add all parameters as long as you keep them in the same order as your initializer

address2.latitude // 22.0

swift3 optional value issue

This behavior is normal if the properties in the struct are also declared as optionals. In this case the unwrapping with optional binding has actually no effect.

To avoid that declare the property as non-optional and assign a default value for example

struct Job {

var activityID = ""
...

}

newJob.activityID = infoDictionary["ActivityID"] ?? ""

But assigning an empty string twice looks cumbersome. I'd add an initializer to the struct to take a dictionary, declare the properties as constants and handle the default value in the init method.

struct Job {

let activityID : String
...

init(dict: [String:String]) {
activityID = dict["ActivityID"] ?? ""
...
}

}

Note:

Please conform to the naming convention that variable names start with a lowercase letter

Swift create custom initializer without parameters with custom name

You need to create a static method:

static func initWithSomeMode() -> YourClass {
let obj = YourClass()
obj.someCustomSetup()
return obj
}

And then you can do this:

let yourClass = YourClass.initWithSomeMode()

Decoding json with optional fields

You should split this into several steps in order to avoid to handle all these optionals in your model.

First create a struct that has only those properties that are guaranteed to be there. ok in your case:

struct OKResult: Codable{
let ok: Bool
}

then create one for your error state and one for your success state:

struct ErrorResult: Codable{
let ok: Bool
let errorCode: Int
let error: String

private enum CodingKeys: String, CodingKey{
case ok, errorCode = "error_code", error
}
}

struct ShortLinkData: Codable {
let ok: Bool
let result: Result
}

struct Result: Codable {
let code, shortLink: String
let fullShortLink: String
let shortLink2: String
let fullShortLink2: String
let shortLink3: String
let fullShortLink3: String
let shareLink: String
let fullShareLink: String
let originalLink: String

enum CodingKeys: String, CodingKey {
case code
case shortLink = "short_link"
case fullShortLink = "full_short_link"
case shortLink2 = "short_link2"
case fullShortLink2 = "full_short_link2"
case shortLink3 = "short_link3"
case fullShortLink3 = "full_short_link3"
case shareLink = "share_link"
case fullShareLink = "full_share_link"
case originalLink = "original_link"
}
}

Then you can decode the data:

guard try JSONDecoder().decode(OKResult.self, from: data).ok else{
let errorResponse = try JSONDecoder().decode(ErrorResult.self, from: data)
//handle error scenario
fatalError(errorResponse.error) // or throw custom error or return nil etc...
}

let shortlinkData = try JSONDecoder().decode(ShortLinkData.self, from: data)

Remarks:

  • Your inits are not necessary.
  • Never use try? this will hide all errors from you
  • you would need to wrap this either in a do catch block or make your function throwing and handle errors further up the tree.

Initializing attributes in a different method

You can skip the init altogether…

class Point {
var x = 1
var y = 1

public func reset() {
x = 1
y = 1
}
}

Optional class initializer parameter in class initializer in Swift

First of all this is not class this is struct and they both are different.

you can easily create optional argument like below.
You also need to mark user property as optional as well.

struct Offer {
let user: User?
let caption: String
let imageURL: String
let creationDate: Date

init(user: User? = nil, dictionary: [String: Any]) {
self.user = user
self.caption = dictionary["caption"] as? String ?? ""
self.imageURL = dictionary["image_url"] as? String ?? ""

let secondsFrom1970 = dictionary["creation_date"] as? Double ?? 0
self.creationDate = Date(timeIntervalSince1970: secondsFrom1970)
}
}


Related Topics



Leave a reply



Submit