I am trying to append values to a string array - swift

func getCategoryNames() {
Alamofire.request(categoriesUrl).responseJSON { (response) in
if ((response.result.value) != nil) {
var jsonVar = response.result.value as! [String: Any]
if let results = jsonVar["result"] as? [[String: Any]] {
for result in results {
if let names = result["name"] as? String {
var tuy = [""]
tuy.append(names)
I am trying to put those value(names) inside tab(titleNames: tuy)
But it is printing only the last element of the array
Url is
let categoriesUrl = "https://cmsbmnc.agritechie.com/client/categories/"
I need the output like this tuy = ["ABC", "DEF","XYZ"]
let configure = SGPageTitleViewConfigure()
configure.indicatorStyle = .Default
configure.titleAdditionalWidth = 35
self.pageTitleView = SGPageTitleView(frame: CGRect(x: 0, y: pageTitleViewY, width: self.view.frame.size.width, height: 80), delegate: self, titleNames: tuy, configure: configure)
self.view.addSubview(self.pageTitleView!)

In each iteration of the loop you are creating a new tuy array.
You have to create the array once before the loop and declare it as regular empty array
func getCategoryNames() {
Alamofire.request(categoriesUrl).responseJSON { (response) in
if let jsonVar = response.result.value as? [String: Any],
let results = jsonVar["result"] as? [[String: Any]] {
var tuy = [String]()
for result in results {
if let name = result["name"] as? String {
tuy.append(name)
or in a more convenient way
func getCategoryNames() {
Alamofire.request(categoriesUrl).responseJSON { (response) in
if let jsonVar = response.result.value as? [String: Any],
let results = jsonVar["result"] as? [[String: Any]] {
let tuy = results.compactMap { $0["name"] as? String }

It is simple!
Remove that string array var tuy = [""] from
func getCategoryNames() {
Alamofire.request(categoriesUrl).responseJSON { (response) in
if ((response.result.value) != nil) {
var jsonVar = response.result.value as! [String: Any]
if let results = jsonVar["result"] as? [[String: Any]] {
for result in results {
if let names = result["name"] as? String {
var tuy = [""]
tuy.append(names)
and declare it above the function.

You can declare variable of array is outside of function.
var tuy = [String]()
Alamofire.request(categoriesUrl).responseJSON { (response) in
if ((response.result.value) != nil) {
var jsonVar = response.result.value as! [String: Any]
if let results = jsonVar["result"] as? [[String: Any]] {
for result in results {
if let names = result["name"] as? String {
tuy.append(names)
}
}
}

Related

Array Append Problems - Swift

I add the data I pulled from the database to Array. I add these arrays I added in an array. But it doesn't add it the way I want it, where am I doing it wrong?
[["...xyz/Uploads/fnzo1PcnjH3M-1653.jpg"], ["...xyz/Uploads/fnzo1PcnjH3M-1653.jpg", "....xyz/Uploads/Kb6kbOQNY0Vi-1670.png"], [...xyz/Uploads/fnzo1PcnjH3M-1653.jpg", "....xyz/Uploads/Kb6kbOQNY0Vi-1670.png", "...xyz/Uploads/PQASvz4ipg9s-1673.jpg"]]
The output is like this but it should be what I want:
[["...xyz/Uploads/fnzo1PcnjH3M-1653.jpg", "...xyz/Uploads/fnzo1PcnjH3M-1653.jpg", "....xyz/Uploads/Kb6kbOQNY0Vi-1670.png"], ["...xyz/Uploads/fnzo1PcnjH3M-1653.jpg", "....xyz/Uploads/Kb6kbOQNY0Vi-1670.png", "...xyz/Uploads/PQASvz4ipg9s-1673.jpg"]]
So the first array is the davetiyefilee array, the second array is the davetiyefilee2 array. The combination of these arrays is the model array.
So : model = [[davetiyefilee], [davetiyefilee2]]
CODE
var model = [[String]]()
var davetiyefilee = [String]()
var davetiyefilee2 = [String]()
#objc func davetiyecek2() {
if let baslik = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.davetiyefilee2.append(s)
self.model.append(self.davetiyefilee2)
DispatchQueue.main.async {
self.refreshNow = true
self.tableVieww.reloadData()
}
}
}
}
}
#objc func davetiyeCEK1() {
if let baslik = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.davetiyefilee.append(s)
self.model.append(self.davetiyefilee)
DispatchQueue.main.async {
self.refreshNow = true
self.tableVieww.reloadData()
}
}
}
}
}
You probably want to append the inner array to the outer array after the loop.
Reloading the table view inside a loop again and again is bad practice anyway.
And where is the do - catch block?
var model = [[String]]()
var davetiyefilee = [String]()
var davetiyefilee2 = [String]()
#objc func davetiyecek2() {
do {
if let baslik = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.davetiyefilee2.append(s)
}
}
self.model.append(self.davetiyefilee2)
DispatchQueue.main.async {
self.refreshNow = true
self.tableVieww.reloadData()
}
}
} catch { print(error) }
}
#objc func davetiyeCEK1() {
do {
if let baslik = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] {
for review in baslik {
if let soru_baslik = review["davetiyefilee"] as? String {
let s = String(describing: soru_baslik)
self.davetiyefilee.append(s)
}
}
self.model.append(self.davetiyefilee)
DispatchQueue.main.async {
self.refreshNow = true
self.tableVieww.reloadData()
}
}
} catch { print(error) }
}

Posts Being Uploaded Randomly in Collection View - Swift & Firebase

I have been refactoring my code and now I'm having trouble with the posts.
Whenever I add a new post to the collection view, it is being added in a random cell and out of order, instead of in the first post.
I know the reason is the fetchuser function and from what I'm being told due to the asynchronous loading, but don't know what to do in order to correct this.
Could someone help me figure out what to do so that my posts are added in the first cell?
#objc func observePostsAdoption() {
let postsRef = Database.database().reference().child("posts")
postsRef.queryOrdered(byChild: "postType").queryEqual(toValue: "adopt").observe(.value) { (snapshot) in
var tempPost = [Posts]()
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot {
let dict = childSnapshot.value as? [String: Any]
let newAdoptiondPost = Posts.transformPost(dict: dict!)
//This will look up all users at once
self.fetchUser(userid: newAdoptiondPost.userid!, completed: {
tempPost.insert(newAdoptiondPost, at: 0)
DispatchQueue.main.async {
self.postsadoption = tempPost
self.adoptionCollectionView.reloadData()
self.refresherAdoption.endRefreshing()
}
})
}
}
}
}
func fetchUser(userid: String, completed: #escaping ()-> Void ) {
Database.database().reference().child("users").child(userid).observeSingleEvent(of: .value) { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
let user = UserProfile.transformUser(dict: dict)
self.users.insert(user, at: 0)
completed()
}
}
}
Here's my Post Struct
class Posts {
//UserView
var uid: String?
var author: UserProfile?
var timestamp: Date?
var userid: String?
func getDateFormattedString() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "MMM d, HH:mm"
return formatter.string(from: self.timestamp!)
}
//Image
var photoUrl: URL?
//PostInformation View
var city: String?
var municipality: String?
var name: String?
var breed : String?
var phone : String?
var address : String?
var petType: String?
var genderType: String?
var comments: String?
}
extension Posts {
static func transformPost(dict: [String: Any]) -> Posts {
let post = Posts()
//Post Picture
let photoUrl = dict["photoUrl"] as? String
post.photoUrl = URL(string: photoUrl!)
//INFO POSTS
post.userid = dict["userid"] as? String
post.city = dict["city"] as? String
post.municipality = dict["municipality"] as? String
post.name = dict["name"] as? String
post.breed = dict["breed"] as? String
post.phone = dict["phone"] as? String
post.address = dict["address"] as? String
post.comments = dict["comments"] as? String
post.petType = dict["petType"] as? String
post.genderType = dict["gender"] as? String
let timestamp = dict["timestamp"] as? Double
post.timestamp = Date(timeIntervalSince1970: timestamp!/1000)
return post
}
}
If you already have the posts ordered by post type you can just do sorting depending on the timestamp. For example
#objc func observePostsAdoption() {
let postsRef = Database.database().reference().child("posts")
postsRef.queryOrdered(byChild: "postType").queryEqual(toValue: "adopt").observe(.value) { (snapshot) in
var tempPost = [Posts]()
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot {
let dict = childSnapshot.value as? [String: Any]
let newAdoptiondPost = Posts.transformPost(dict: dict!)
//This will look up all users at once
self.fetchUser(userid: newAdoptiondPost.userid!, completed: {
tempPost.insert(newAdoptiondPost, at: 0)
DispatchQueue.main.async {
self.postsadoption = tempPost
self.postsadoption.sort { (p1, p2) -> Bool in
return p1.timeStamp?.compare(p2.timeStamp!) == .orderdDescending
}
self.adoptionCollectionView.reloadData()
self.refresherAdoption.endRefreshing()
}
})
}
}
}
}
With that the posts adoption array will be sorted depending on the timestamp that you have.

Parsing array in Swift2.2

How to get body and title data from the below response. I'm totally stuck
[aps: {
alert = {
body = test123;
title = test123;
};
},
gcm.message_id: 0:4a]
If you are working with notification then you need to access the data like this way.
if let info = notification.userInfo as? [String: AnyObject],
let apsDic = info["aps"] as? [String: AnyObject],
let alertDic = info["alert"] as? [String: AnyObject] {
if let body = alertDic["body"] as? String {
print(body)
}
if let title = alertDic["title"] as? String {
print(title)
}
}

Return from initializer without initializing all stored properties error - yet everything is initialized

I'm running into this weird error. it was working fine until I added the image and imageString values and then this error happened:
Return from initializer without initializing all stored properties
I thought I initialized all the properties, not sure why this error is happening. Here is the custom object class
class JSONObject {
private let baseImageURL = "https://website.com"
var airbnbUS: Int
var airbnbLocal: Int
var imageString: String
var image: URL
init(airbnbUS: Int, airbnbLocal: Int, imageString: String, image: URL ){
self.airbnbUS = airbnbUS
self.airbnbLocal = airbnbLocal
self.imageString = imageString
self.image = image
}
init(resultsDictionary:[String: Any]){
guard let cost = resultsDictionary["cost"] as? [String: Any],
let airbnb = cost["airbnb_median"] as? [String : Any],
let usd = airbnb["USD"] as? Int,
let chf = airbnb["CHF"] as? Int
else {
airbnbUS = 0
airbnbLocal = 0
return
}
airbnbUS = usd
airbnbLocal = chf
guard let media = (resultsDictionary["media"] as? [String: Any]),
let imageDictionary = media["image"] as? [String: Any],
let image1000 = imageDictionary["1000"] as? String
else {
imageString = ""
image = URL(string: "\(baseImageURL)")!
return
}
imageString = image1000
image = URL(string: "\(baseImageURL)\(imageString)")!
}
}
The issue is in your resultsDictionary initializer. The return in your first guard statement could return from the initializer early, and the following guard statement (and the code where you assign the image and imageString properties) might not execute.
One solution is to change the first guard statement to an if-let statement.
init(resultsDictionary:[String: Any]){
if let cost = resultsDictionary["cost"] as? [String: Any],
let airbnb = cost["airbnb_median"] as? [String : Any],
let usd = airbnb["USD"] as? Int,
let chf = airbnb["CHF"] as? Int
{
airbnbUS = usd
airbnbLocal = chf
} else {
airbnbUS = 0
airbnbLocal = 0
}
guard let media = (resultsDictionary["media"] as? [String: Any]),
let imageDictionary = media["image"] as? [String: Any],
let image1000 = imageDictionary["1000"] as? String
else {
imageString = ""
image = URL(string: "\(baseImageURL)")!
return
}
imageString = image1000
image = URL(string: "\(baseImageURL)\(imageString)")!
}

possible to cast this Alamofire result to an array of dictionaries

I am not an iOS dev and have to make a few changes to a Swift / AlamoFire project (not mine) and am a bit lost.
I have the following JSON:
{"metro_locations":
[
{
"name":"Ruby Red"
},
{
"name":"Blue Ocean"
}
]
}
class (I know that there are issues here):
class Location{
var name=""
init(obj:tmp){
self.name=tmp["name"]
}
}
and need to make an AlamoFire call
Alamofire.request(.GET, "https://www.domain.com/arc/v1/api/metro_areas/1", parameters: nil)
.responseJSON { response in
if let dataFromNetworking = response.result.value {
let metroLocations = dataFromNetworking["metro_locations"]
var locations: [Location]=[]
for tmp in metroLocations as! [Dictionary] { // <- not working, Generic Paramter 'Key' could not be inferred
let location=Location.init(obj: tmp)
locations.append(location)
}
}
}
I have included the error msg, the "not working" but feel that there are issues in other parts too (like expecting a dictionary in the initialization). What does the 'Key' could not be inferred mean and are there other changes I need to make?
edit #1
I have updated my Location to this to reflect your suggestion:
init?(dictionary: [String: AnyObject]) {
guard let id = dictionary["id"] else { return nil }
guard let name = dictionary["name"] else { return nil }
guard let latitude = dictionary["latitude"] else { return nil }
guard let longitude = dictionary["longitude"] else { return nil }
self.name = name as! String
self.id = id as! Int
self.latitude = latitude as! Double
self.longitude = longitude as! Double
}
but I get the error:
Could not cast value of type 'NSNull' (0x10f387600) to 'NSNumber' (0x10f77f2a0).
like this:
I would think that the guard statement would prevent this. What am I missing?
You can cast metroLocations as an array of dictionaries, namely:
Array<Dictionary<String, String>>
Or, more concisely:
[[String: String]]
Thus:
if let dataFromNetworking = response.result.value {
guard let metroLocations = dataFromNetworking["metro_locations"] as? [[String: String]] else {
print("this was not an array of dictionaries where the values were all strings")
return
}
var locations = [Location]()
for dictionary in metroLocations {
if let location = Location(dictionary: dictionary) {
locations.append(location)
}
}
}
Where
class Location {
let name: String
init?(dictionary: [String: String]) {
guard let name = dictionary["name"] else { return nil }
self.name = name
}
}
Clearly, I used [[String: String]] to represent an array of dictionaries where the values were all strings, as in your example. If the values included objects other than strings (numbers, booleans, etc.), then you might use [[String: AnyObject]].
In your revision, you show us a more complete Location implementation. You should avoid as! forced casting, and instead us as? in the guard statements:
class Location {
let id: Int
let name: String
let latitude: Double
let longitude: Double
init?(dictionary: [String: AnyObject]) {
guard let id = dictionary["id"] as? Int,
let name = dictionary["name"] as? String,
let latitude = dictionary["latitude"] as? Double,
let longitude = dictionary["longitude"] as? Double else {
return nil
}
self.name = name
self.id = id
self.latitude = latitude
self.longitude = longitude
}
}