From 4087326433c8f72441ac72145738ef24bd2ceac4 Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Fri, 9 Jun 2017 23:53:45 +0400 Subject: [PATCH 1/7] Minor refactoring --- TableViewWithMultipleCellTypes/Base.lproj/Main.storyboard | 8 ++++---- TableViewWithMultipleCellTypes/ViewController.swift | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/TableViewWithMultipleCellTypes/Base.lproj/Main.storyboard b/TableViewWithMultipleCellTypes/Base.lproj/Main.storyboard index 751cb46..fe9677d 100644 --- a/TableViewWithMultipleCellTypes/Base.lproj/Main.storyboard +++ b/TableViewWithMultipleCellTypes/Base.lproj/Main.storyboard @@ -1,15 +1,15 @@ - + - + - + @@ -34,7 +34,7 @@ - + diff --git a/TableViewWithMultipleCellTypes/ViewController.swift b/TableViewWithMultipleCellTypes/ViewController.swift index fe7212b..ab0be06 100644 --- a/TableViewWithMultipleCellTypes/ViewController.swift +++ b/TableViewWithMultipleCellTypes/ViewController.swift @@ -9,14 +9,17 @@ import UIKit class ViewController: UIViewController { - + fileprivate let viewModel = ProfileViewModel() @IBOutlet weak var tableView: UITableView? override func viewDidLoad() { super.viewDidLoad() - + setupTableview() + } + + private func setupTableview() { tableView?.dataSource = viewModel tableView?.estimatedRowHeight = 100 @@ -27,5 +30,6 @@ class ViewController: UIViewController { tableView?.register(FriendCell.nib, forCellReuseIdentifier: FriendCell.identifier) tableView?.register(AttributeCell.nib, forCellReuseIdentifier: AttributeCell.identifier) tableView?.register(EmailCell.nib, forCellReuseIdentifier: EmailCell.identifier) + } } From 6e1839a0609ee51afb9b374b219fb0b8212d2ebc Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Fri, 9 Jun 2017 23:54:25 +0400 Subject: [PATCH 2/7] Committing gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..78b97cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +TableViewWithMultipleCellTypes.xcodeproj/xcuserdata/abhishekbedi.xcuserdatad/xcschemes/xcschememanagement.plist + +TableViewWithMultipleCellTypes.xcodeproj/project.xcworkspace/xcuserdata/abhishekbedi.xcuserdatad/UserInterfaceState.xcuserstate From b438106a32bd68dcda848f4a2965f77522888e4d Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Sat, 10 Jun 2017 00:04:48 +0400 Subject: [PATCH 3/7] Using protocol Reusable view to extract reuseidzntifier and win variables --- .../project.pbxproj | 12 ++++++++++++ TableViewWithMultipleCellTypes/AboutCell.swift | 14 +++----------- TableViewWithMultipleCellTypes/AttributeCell.swift | 10 +--------- TableViewWithMultipleCellTypes/EmailCell.swift | 10 +--------- TableViewWithMultipleCellTypes/FriendCell.swift | 10 +--------- .../NamePictureCell.swift | 11 +---------- .../ProfileViewModel.swift | 10 +++++----- .../Protocols/Protocols.swift | 14 ++++++++++++++ .../ViewController.swift | 10 +++++----- 9 files changed, 43 insertions(+), 58 deletions(-) create mode 100644 TableViewWithMultipleCellTypes/Protocols/Protocols.swift diff --git a/TableViewWithMultipleCellTypes.xcodeproj/project.pbxproj b/TableViewWithMultipleCellTypes.xcodeproj/project.pbxproj index 40584f2..2ede7af 100644 --- a/TableViewWithMultipleCellTypes.xcodeproj/project.pbxproj +++ b/TableViewWithMultipleCellTypes.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 36C0EC911EB00C4A0039B330 /* ServerData.json in Resources */ = {isa = PBXBuildFile; fileRef = 36C0EC901EB00C4A0039B330 /* ServerData.json */; }; 36C0EC931EB00C710039B330 /* ProfileModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C0EC921EB00C710039B330 /* ProfileModel.swift */; }; 36C0EC951EB00E290039B330 /* ProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C0EC941EB00E290039B330 /* ProfileViewModel.swift */; }; + CFB17DC11EEB34CF00C437D2 /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFB17DC01EEB34CF00C437D2 /* Protocols.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -48,6 +49,7 @@ 36C0EC901EB00C4A0039B330 /* ServerData.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ServerData.json; sourceTree = ""; }; 36C0EC921EB00C710039B330 /* ProfileModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileModel.swift; sourceTree = ""; }; 36C0EC941EB00E290039B330 /* ProfileViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileViewModel.swift; sourceTree = ""; }; + CFB17DC01EEB34CF00C437D2 /* Protocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Protocols.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,6 +103,7 @@ 36C0EC7E1EB00BFC0039B330 /* AppDelegate.swift */, 36C0EC801EB00BFC0039B330 /* ViewController.swift */, 36C0EC901EB00C4A0039B330 /* ServerData.json */, + CFB17DC21EEB34D300C437D2 /* Protocols */, 36C0EC821EB00BFC0039B330 /* Main.storyboard */, 36C0EC851EB00BFC0039B330 /* Assets.xcassets */, 36C0EC871EB00BFC0039B330 /* LaunchScreen.storyboard */, @@ -111,6 +114,14 @@ path = TableViewWithMultipleCellTypes; sourceTree = ""; }; + CFB17DC21EEB34D300C437D2 /* Protocols */ = { + isa = PBXGroup; + children = ( + CFB17DC01EEB34CF00C437D2 /* Protocols.swift */, + ); + path = Protocols; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -195,6 +206,7 @@ 367B20181ED20BC0000F2BFA /* AttributeCell.swift in Sources */, 36C0EC811EB00BFC0039B330 /* ViewController.swift in Sources */, 36C0EC951EB00E290039B330 /* ProfileViewModel.swift in Sources */, + CFB17DC11EEB34CF00C437D2 /* Protocols.swift in Sources */, 36C0EC7F1EB00BFC0039B330 /* AppDelegate.swift in Sources */, 367B200C1ED204B2000F2BFA /* NamePictureCell.swift in Sources */, 367B201C1ED211F3000F2BFA /* EmailCell.swift in Sources */, diff --git a/TableViewWithMultipleCellTypes/AboutCell.swift b/TableViewWithMultipleCellTypes/AboutCell.swift index 260ec0c..27e41e6 100644 --- a/TableViewWithMultipleCellTypes/AboutCell.swift +++ b/TableViewWithMultipleCellTypes/AboutCell.swift @@ -8,25 +8,17 @@ import UIKit -class AboutCell: UITableViewCell { - +class AboutCell: UITableViewCell, ReusableView { + @IBOutlet weak var aboutLabel: UILabel? var item: ProfileViewModelItem? { didSet { - guard let item = item as? ProfileViewModelAboutItem else { + guard let item = item as? ProfileViewModelAboutItem else { return } aboutLabel?.text = item.about } } - - static var nib:UINib { - return UINib(nibName: identifier, bundle: nil) - } - - static var identifier: String { - return String(describing: self) - } } diff --git a/TableViewWithMultipleCellTypes/AttributeCell.swift b/TableViewWithMultipleCellTypes/AttributeCell.swift index 0f66c11..ae74895 100644 --- a/TableViewWithMultipleCellTypes/AttributeCell.swift +++ b/TableViewWithMultipleCellTypes/AttributeCell.swift @@ -8,7 +8,7 @@ import UIKit -class AttributeCell: UITableViewCell { +class AttributeCell: UITableViewCell, ReusableView { @IBOutlet weak var titleLabel: UILabel? @IBOutlet weak var valueLabel: UILabel? @@ -19,12 +19,4 @@ class AttributeCell: UITableViewCell { valueLabel?.text = item?.value } } - - static var nib:UINib { - return UINib(nibName: identifier, bundle: nil) - } - - static var identifier: String { - return String(describing: self) - } } diff --git a/TableViewWithMultipleCellTypes/EmailCell.swift b/TableViewWithMultipleCellTypes/EmailCell.swift index 54cafaf..c4370e1 100644 --- a/TableViewWithMultipleCellTypes/EmailCell.swift +++ b/TableViewWithMultipleCellTypes/EmailCell.swift @@ -8,7 +8,7 @@ import UIKit -class EmailCell: UITableViewCell { +class EmailCell: UITableViewCell, ReusableView { @IBOutlet weak var emailLabel: UILabel? @@ -21,12 +21,4 @@ class EmailCell: UITableViewCell { emailLabel?.text = item.email } } - - static var nib:UINib { - return UINib(nibName: identifier, bundle: nil) - } - - static var identifier: String { - return String(describing: self) - } } diff --git a/TableViewWithMultipleCellTypes/FriendCell.swift b/TableViewWithMultipleCellTypes/FriendCell.swift index ebd8c25..7d16dbc 100644 --- a/TableViewWithMultipleCellTypes/FriendCell.swift +++ b/TableViewWithMultipleCellTypes/FriendCell.swift @@ -8,7 +8,7 @@ import UIKit -class FriendCell: UITableViewCell { +class FriendCell: UITableViewCell, ReusableView { @IBOutlet weak var pictureImageView: UIImageView? @IBOutlet weak var nameLabel: UILabel? @@ -27,14 +27,6 @@ class FriendCell: UITableViewCell { } } - static var nib:UINib { - return UINib(nibName: identifier, bundle: nil) - } - - static var identifier: String { - return String(describing: self) - } - override func awakeFromNib() { super.awakeFromNib() diff --git a/TableViewWithMultipleCellTypes/NamePictureCell.swift b/TableViewWithMultipleCellTypes/NamePictureCell.swift index fe1123b..ceb5d2e 100644 --- a/TableViewWithMultipleCellTypes/NamePictureCell.swift +++ b/TableViewWithMultipleCellTypes/NamePictureCell.swift @@ -8,7 +8,7 @@ import UIKit -class NamePictureCell: UITableViewCell { +class NamePictureCell: UITableViewCell, ReusableView { @IBOutlet weak var nameLabel: UILabel? @IBOutlet weak var pictureImageView: UIImageView? @@ -23,15 +23,6 @@ class NamePictureCell: UITableViewCell { pictureImageView?.image = UIImage(named: item.pictureUrl) } } - - static var nib:UINib { - return UINib(nibName: identifier, bundle: nil) - } - - static var identifier: String { - return String(describing: self) - } - override func awakeFromNib() { super.awakeFromNib() diff --git a/TableViewWithMultipleCellTypes/ProfileViewModel.swift b/TableViewWithMultipleCellTypes/ProfileViewModel.swift index 000e40f..e361ebf 100644 --- a/TableViewWithMultipleCellTypes/ProfileViewModel.swift +++ b/TableViewWithMultipleCellTypes/ProfileViewModel.swift @@ -74,28 +74,28 @@ extension ProfileViewModel: UITableViewDataSource { let item = items[indexPath.section] switch item.type { case .nameAndPicture: - if let cell = tableView.dequeueReusableCell(withIdentifier: NamePictureCell.identifier, for: indexPath) as? NamePictureCell { + if let cell = tableView.dequeueReusableCell(withIdentifier: NamePictureCell.reuseIdentifier, for: indexPath) as? NamePictureCell { cell.item = item return cell } case .about: - if let cell = tableView.dequeueReusableCell(withIdentifier: AboutCell.identifier, for: indexPath) as? AboutCell { + if let cell = tableView.dequeueReusableCell(withIdentifier: AboutCell.reuseIdentifier, for: indexPath) as? AboutCell { cell.item = item return cell } case .email: - if let cell = tableView.dequeueReusableCell(withIdentifier: EmailCell.identifier, for: indexPath) as? EmailCell { + if let cell = tableView.dequeueReusableCell(withIdentifier: EmailCell.reuseIdentifier, for: indexPath) as? EmailCell { cell.item = item return cell } case .friend: - if let item = item as? ProfileViewModeFriendsItem, let cell = tableView.dequeueReusableCell(withIdentifier: FriendCell.identifier, for: indexPath) as? FriendCell { + if let item = item as? ProfileViewModeFriendsItem, let cell = tableView.dequeueReusableCell(withIdentifier: FriendCell.reuseIdentifier, for: indexPath) as? FriendCell { let friend = item.friends[indexPath.row] cell.item = friend return cell } case .attribute: - if let item = item as? ProfileViewModeAttributeItem, let cell = tableView.dequeueReusableCell(withIdentifier: AttributeCell.identifier, for: indexPath) as? AttributeCell { + if let item = item as? ProfileViewModeAttributeItem, let cell = tableView.dequeueReusableCell(withIdentifier: AttributeCell.reuseIdentifier, for: indexPath) as? AttributeCell { cell.item = item.attributes[indexPath.row] return cell } diff --git a/TableViewWithMultipleCellTypes/Protocols/Protocols.swift b/TableViewWithMultipleCellTypes/Protocols/Protocols.swift new file mode 100644 index 0000000..ca07113 --- /dev/null +++ b/TableViewWithMultipleCellTypes/Protocols/Protocols.swift @@ -0,0 +1,14 @@ +import Foundation +import UIKit + +protocol ReusableView: class {} + +extension ReusableView where Self: UIView { + static var reuseIdentifier: String { + return String(describing: self) + } + + static var nib:UINib { + return UINib(nibName: reuseIdentifier, bundle: nil) + } +} diff --git a/TableViewWithMultipleCellTypes/ViewController.swift b/TableViewWithMultipleCellTypes/ViewController.swift index ab0be06..80a0528 100644 --- a/TableViewWithMultipleCellTypes/ViewController.swift +++ b/TableViewWithMultipleCellTypes/ViewController.swift @@ -25,11 +25,11 @@ class ViewController: UIViewController { tableView?.estimatedRowHeight = 100 tableView?.rowHeight = UITableViewAutomaticDimension - tableView?.register(AboutCell.nib, forCellReuseIdentifier: AboutCell.identifier) - tableView?.register(NamePictureCell.nib, forCellReuseIdentifier: NamePictureCell.identifier) - tableView?.register(FriendCell.nib, forCellReuseIdentifier: FriendCell.identifier) - tableView?.register(AttributeCell.nib, forCellReuseIdentifier: AttributeCell.identifier) - tableView?.register(EmailCell.nib, forCellReuseIdentifier: EmailCell.identifier) + tableView?.register(AboutCell.nib, forCellReuseIdentifier: AboutCell.reuseIdentifier) + tableView?.register(NamePictureCell.nib, forCellReuseIdentifier: NamePictureCell.reuseIdentifier) + tableView?.register(FriendCell.nib, forCellReuseIdentifier: FriendCell.reuseIdentifier) + tableView?.register(AttributeCell.nib, forCellReuseIdentifier: AttributeCell.reuseIdentifier) + tableView?.register(EmailCell.nib, forCellReuseIdentifier: EmailCell.reuseIdentifier) } } From c4391c4a112cede718a45331b79d99464cbfe706 Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Sat, 10 Jun 2017 00:10:45 +0400 Subject: [PATCH 4/7] Adding extension to ProfileViewModelItem Removing repetitive code of rowCount = 1 from View models --- TableViewWithMultipleCellTypes/FriendCell.swift | 6 ------ .../ProfileViewModel.swift | 17 +++++------------ 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/TableViewWithMultipleCellTypes/FriendCell.swift b/TableViewWithMultipleCellTypes/FriendCell.swift index 7d16dbc..23bdb1b 100644 --- a/TableViewWithMultipleCellTypes/FriendCell.swift +++ b/TableViewWithMultipleCellTypes/FriendCell.swift @@ -36,12 +36,6 @@ class FriendCell: UITableViewCell, ReusableView { pictureImageView?.backgroundColor = UIColor.lightGray } - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - override func prepareForReuse() { super.prepareForReuse() diff --git a/TableViewWithMultipleCellTypes/ProfileViewModel.swift b/TableViewWithMultipleCellTypes/ProfileViewModel.swift index e361ebf..e6e2c06 100644 --- a/TableViewWithMultipleCellTypes/ProfileViewModel.swift +++ b/TableViewWithMultipleCellTypes/ProfileViewModel.swift @@ -23,6 +23,11 @@ protocol ProfileViewModelItem { var rowCount: Int { get } } + +extension ProfileViewModelItem { + var rowCount: Int { return 1 } +} + class ProfileViewModel: NSObject { var items = [ProfileViewModelItem]() @@ -118,10 +123,6 @@ class ProfileViewModelNamePictureItem: ProfileViewModelItem { return "Main Info" } - var rowCount: Int { - return 1 - } - var name: String var pictureUrl: String @@ -140,10 +141,6 @@ class ProfileViewModelAboutItem: ProfileViewModelItem { return "About" } - var rowCount: Int { - return 1 - } - var about: String init(about: String) { @@ -160,10 +157,6 @@ class ProfileViewModelEmailItem: ProfileViewModelItem { return "Email" } - var rowCount: Int { - return 1 - } - var email: String init(email: String) { From 5886a5aeda042ff643faeb0e223c09064692ed5e Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Sat, 10 Jun 2017 02:16:46 +0400 Subject: [PATCH 5/7] Refactoring Profile Model/ViewModel The ViewModel items can be aptly configured in ProfileModel from where they are actually initialized. --- .../ProfileModel.swift | 34 +++++++++++++++++++ .../ProfileViewModel.swift | 28 +++------------ 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/TableViewWithMultipleCellTypes/ProfileModel.swift b/TableViewWithMultipleCellTypes/ProfileModel.swift index eb8974f..d065ddd 100644 --- a/TableViewWithMultipleCellTypes/ProfileModel.swift +++ b/TableViewWithMultipleCellTypes/ProfileModel.swift @@ -47,6 +47,40 @@ class Profile { return nil } } + + func setupItems(fromProfile profile: Profile) -> [ProfileViewModelItem] { + var items = [ProfileViewModelItem]() + + if let name = profile.fullName, let pictureUrl = profile.pictureUrl { + let nameAndPictureItem = ProfileViewModelNamePictureItem(name: name, pictureUrl: pictureUrl) + items.append(nameAndPictureItem) + } + + if let about = profile.about { + let aboutItem = ProfileViewModelAboutItem(about: about) + items.append(aboutItem) + } + + if let email = profile.email { + let dobItem = ProfileViewModelEmailItem(email: email) + items.append(dobItem) + } + + let attributes = profile.profileAttributes + if !attributes.isEmpty { + let attributesItem = ProfileViewModeAttributeItem(attributes: attributes) + items.append(attributesItem) + } + + let friends = profile.friends + if !profile.friends.isEmpty { + let friendsItem = ProfileViewModeFriendsItem(friends: friends) + items.append(friendsItem) + } + + return items + } + } class Friend { diff --git a/TableViewWithMultipleCellTypes/ProfileViewModel.swift b/TableViewWithMultipleCellTypes/ProfileViewModel.swift index e6e2c06..a775217 100644 --- a/TableViewWithMultipleCellTypes/ProfileViewModel.swift +++ b/TableViewWithMultipleCellTypes/ProfileViewModel.swift @@ -33,36 +33,16 @@ class ProfileViewModel: NSObject { override init() { super.init() - guard let data = dataFromFile("ServerData"), let profile = Profile(data: data) else { + guard let data = dataFromFile("ServerData") else { return } - if let name = profile.fullName, let pictureUrl = profile.pictureUrl { - let nameAndPictureItem = ProfileViewModelNamePictureItem(name: name, pictureUrl: pictureUrl) - items.append(nameAndPictureItem) - } - - if let about = profile.about { - let aboutItem = ProfileViewModelAboutItem(about: about) - items.append(aboutItem) - } - - if let email = profile.email { - let dobItem = ProfileViewModelEmailItem(email: email) - items.append(dobItem) + guard let profile = Profile(data: data) else { + return } - let attributes = profile.profileAttributes - if !attributes.isEmpty { - let attributesItem = ProfileViewModeAttributeItem(attributes: attributes) - items.append(attributesItem) - } + items = profile.setupItems(fromProfile: profile) - let friends = profile.friends - if !profile.friends.isEmpty { - let friendsItem = ProfileViewModeFriendsItem(friends: friends) - items.append(friendsItem) - } } } From c210b05231834048138184c8a3fbcf754ff40f72 Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Sat, 10 Jun 2017 02:19:36 +0400 Subject: [PATCH 6/7] Combining guard statements --- TableViewWithMultipleCellTypes/ProfileViewModel.swift | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/TableViewWithMultipleCellTypes/ProfileViewModel.swift b/TableViewWithMultipleCellTypes/ProfileViewModel.swift index a775217..06c8a92 100644 --- a/TableViewWithMultipleCellTypes/ProfileViewModel.swift +++ b/TableViewWithMultipleCellTypes/ProfileViewModel.swift @@ -33,16 +33,13 @@ class ProfileViewModel: NSObject { override init() { super.init() - guard let data = dataFromFile("ServerData") else { - return - } - - guard let profile = Profile(data: data) else { + guard + let data = dataFromFile("ServerData"), + let profile = Profile(data: data) else { return } items = profile.setupItems(fromProfile: profile) - } } From aba8507436bd7e05c84350dd2bee403afcb24cea Mon Sep 17 00:00:00 2001 From: Abedi3 Date: Sat, 10 Jun 2017 02:31:46 +0400 Subject: [PATCH 7/7] =?UTF-8?q?Refactoring=20[String:=20Any])=20->=20JSOND?= =?UTF-8?q?ictionary=20=F0=9F=98=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TableViewWithMultipleCellTypes/ProfileModel.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/TableViewWithMultipleCellTypes/ProfileModel.swift b/TableViewWithMultipleCellTypes/ProfileModel.swift index d065ddd..7f0c1e3 100644 --- a/TableViewWithMultipleCellTypes/ProfileModel.swift +++ b/TableViewWithMultipleCellTypes/ProfileModel.swift @@ -8,6 +8,8 @@ import Foundation +typealias JSONDictionary = [String: Any] + public func dataFromFile(_ filename: String) -> Data? { @objc class TestClass: NSObject { } @@ -28,17 +30,17 @@ class Profile { init?(data: Data) { do { - if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any], let body = json["data"] as? [String: Any] { + if let json = try JSONSerialization.jsonObject(with: data) as? JSONDictionary, let body = json["data"] as? JSONDictionary { self.fullName = body["fullName"] as? String self.pictureUrl = body["pictureUrl"] as? String self.about = body["about"] as? String self.email = body["email"] as? String - if let friends = body["friends"] as? [[String: Any]] { + if let friends = body["friends"] as? [JSONDictionary] { self.friends = friends.map { Friend(json: $0) } } - if let profileAttributes = body["profileAttributes"] as? [[String: Any]] { + if let profileAttributes = body["profileAttributes"] as? [JSONDictionary] { self.profileAttributes = profileAttributes.map { Attribute(json: $0) } } } @@ -87,7 +89,7 @@ class Friend { var name: String? var pictureUrl: String? - init(json: [String: Any]) { + init(json: JSONDictionary) { self.name = json["name"] as? String self.pictureUrl = json["pictureUrl"] as? String } @@ -97,7 +99,7 @@ class Attribute { var key: String? var value: String? - init(json: [String: Any]) { + init(json: JSONDictionary) { self.key = json["key"] as? String self.value = json["value"] as? String }