I am using the following code :
PFCloud.callFunctionInBackground("getFollowers", withParameters: ["userId":id!,"offset":0 ]) { (result , error) -> Void in
if let result = result as? [Follower] {
print(result)
for fl in result {
print(fl)
}
}
}
}
the print(result) shows the following:
[<Follower: 0x7f8f7253c2f0, objectId: 5h3pcK0GTK, localId: (null)> {
Likes = 2;
description = cggggg;
image = "<PFFile: 0x7f8f7253b220>";
isFollowing = 0;
pushed = 1;
user = "<Spoke.SPKUser: 0x7f8f72564690, objectId: ESczJnhc7c, localId: (null)>";
voice = "<PFFile: 0x7f8f7253e8e0>";}]
the weird thing is print(fl) shows :
fl myapp.Follower 0x00007fe0c1e6aa90 0x00007fe0c1e6aa90
Parse.PFObject PFObject
Likes Int! nil
image PFFile! nil
isFollowing Bool! nil
pushed Bool! nil
user Spoke.SPKUser! nil
voice PFFile! nil
My question is why I cannot get an array of mapped follower objects ?
I just added #NSManaged in front of every property of my PFObject subclass and it worked
Related
I'm getting an array of dictionaries from the server. Then I'm trying to convert it to jsonDictionary it seems like I'm doing something wrong. How can I also init my Users model?
Here is the code:
func getSearchedUsers(key: String, completion: #escaping(SearchedUsers?) -> Void) {
if let url = URL(string: baseURL + "search?qerty=\(key)") {
Alamofire.request(url).responseJSON { (response) in
if let array = response.result.value as? [[String:Any]] {
var dictionary = [String:Any]()
for item in array {
for (key, value) in item {
dictionary.updateValue(value, forKey: key)
}
}
} else {
completion(nil)
}
}
}
}
And here is the model:
class SearchedUsers {
let id: Int
let username: String?
let fullName: String?
let profilePicture: URL?
let isPrivate: Bool
init(data: [String: Any]) {
id = data["id"] as! Int
username = data["username"] as? String
fullName = data["fullName"] as? String
isPrivate = data["isPrivate"] as! Bool
profilePicture = data["profilePicUrl"] as? URL
}
}
How can I get this to work?
Here is the response I get:
[Result]: SUCCESS: (
{
byline = "21.9k followers";
followerCount = 21911;
friendshipStatus = {
following = 0;
"incoming_request" = 0;
"is_bestie" = 0;
"is_private" = 0;
"outgoing_request" = 0;
};
fullName = "Undefined Variable";
hasAnonymousProfilePicture = 0;
id = 8513861541;
isPrivate = 0;
isVerified = 0;
mutualFollowersCount = 0;
picture = "https://scontent-ams3-1.cdninstagram.com/vp/885ac17fe17809de22790f0559f61877/5CD13A1C/t51.2885-19/s150x150/39312159_480582069091253_3011569611268161536_n.jpg?_nc_ht=scontent-ams3-1.cdninstagram.com";
pk = 8513861541;
profilePicId = "1857507164564653723_8513861541";
profilePicUrl = "https://scontent-ams3-1.cdninstagram.com/vp/885ac17fe17809de22790f0559f61877/5CD13A1C/t51.2885-19/s150x150/39312159_480582069091253_3011569611268161536_n.jpg?_nc_ht=scontent-ams3-1.cdninstagram.com";
reelAutoArchive = on;
username = "i_am_variable";
},
{
byline = "467 followers";
followerCount = 467;
friendshipStatus = {
following = 0;
"incoming_request" = 0;
"is_bestie" = 0;
"is_private" = 0;
"outgoing_request" = 0;
};
fullName = undefined;
hasAnonymousProfilePicture = 0;
id = 8657882817;
isPrivate = 0;
isVerified = 0;
latestReelMedia = 1547794887;
mutualFollowersCount = 0;
picture = "https://scontent-ams3-1.cdninstagram.com/vp/fb3c992c899aa269bdce2c4c1db8575b/5CD068BA/t51.2885-19/s150x150/46378106_2062632390480778_1266491662662631424_n.jpg?_nc_ht=scontent-ams3-1.cdninstagram.com";
pk = 8657882817;
profilePicId = "1931972067016763185_8657882817";
profilePicUrl = "https://scontent-ams3-1.cdninstagram.com/vp/fb3c992c899aa269bdce2c4c1db8575b/5CD068BA/t51.2885-19/s150x150/46378106_2062632390480778_1266491662662631424_n.jpg?_nc_ht=scontent-ams3-1.cdninstagram.com";
reelAutoArchive = on;
username = "undefi.ned";
})
It's an array of dictionaries, I need to parse it in a proper way. That's my main issue.
If you know how to parse dictionary, then you should know how to make one ;) There are tools out there to make your own model class, like: http://www.jsoncafe.com/
EDIT: As suggested by Robert in the comment section below, you can learn Decodable.
You can use that to give yourself an idea how a model class could or should look like. Use it however you like. In a decent project, there could be tons of data, and you don't want to make a class model out of it especially if you're the only one handling the iOS project.
So we suppose, we have this json data, based on your post:
{
"id": 1,
"username": "dd",
"fullName": "dd",
"profilePicture": "ddd",
"isPrivate": true
}
We could make a model out of it like so:
//
// UserRootClass.swift
// Model Generated using http://www.jsoncafe.com/
// Created on January 18, 2019
import Foundation
class UserRootClass : NSObject {
var fullName : String!
var id : Int!
var isPrivate : Bool!
var profilePicture : String!
var username : String!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
fullName = dictionary["fullName"] as? String
id = dictionary["id"] as? Int
isPrivate = dictionary["isPrivate"] as? Bool
profilePicture = dictionary["profilePicture"] as? String
username = dictionary["username"] as? String
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if fullName != nil{
dictionary["fullName"] = fullName
}
if id != nil{
dictionary["id"] = id
}
if isPrivate != nil{
dictionary["isPrivate"] = isPrivate
}
if profilePicture != nil{
dictionary["profilePicture"] = profilePicture
}
if username != nil{
dictionary["username"] = username
}
return dictionary
}
}
The model class above was made using the tool I gave above, but I removed the NSCoding protocol methods.
I hope this helps! Good luck and welcome to Stackoverflow.
You can use Decodable if you have Struct instead of Class for easy parsing. Here is the example in Alamofire 5.0
struct SearchedUsers: Decodable {
let id: Int
let username: String?
let fullName: String?
let profilePicture: URL?
let isPrivate: Bool
}
AF.request("http://url_endpoint/").responseData { response in
do {
// data we are getting from network request
let decoder = JSONDecoder()
let response = try decoder.decode([SearchedUsers].self, from: response.data!)
} catch { print(error) }
}
I have a query that gets objects from the server I'm then reducing the number of objects by matching "packName" to "className" which should just give me the children of "packName".
from this i am populating an array of struct items and pulling out the data for the first index of the array.
this is fine but I'm just a bit concerned that if the number of children increases this may slow processing down. so i was wondering if there was a way to just retrieve the first item of the for loop, which is all I'm after as the query has been sorted in ascending order.
this is the function code below.
class func createHistory(packName: String, completeBlock: ((Bool) -> Void)? = nil) {
struct initialDataStruct {
var packNameStruct : String
var packIdStruct : String
var partNameStruct : String
var partIdStruct : String
var partIndexStruct : Int
}
var initialDataArray = [initialDataStruct]()
let historyClass = PFObject(className: packName)
let query = PFQuery(className: "Part")
query.includeKey("fromPack")
query.order(byAscending: "partName")
query.fromLocalDatastore()
query.findObjectsInBackground { (objects, error) in
if error != nil {
print(error!)
}
else if let parts = objects {
for object in parts {
// if the fromPack column has data
if let fromPack = object.object(forKey: "fromPack") as? PFObject {
// create the class name from the pack name
if let className = (fromPack.object(forKey: "packName") as? String) {
// packName was sent from JVC
// this will limit array items to how ever many children packName has
if packName == className {
// because its sorted could probably just get the first item here
let packName = fromPack.object(forKey: "packName") as! String
let packId = fromPack.objectId as String!
let partName = object.object(forKey: "partName") as! String
let partId = object.objectId as String!
let partIndex = 0
initialDataArray.append(initialDataStruct(packNameStruct: packName,
packIdStruct: packId!,
partNameStruct: partName,
partIdStruct: partId!,
partIndexStruct: partIndex))
}
}
}
} // for
historyClass.add(initialDataArray[0].packNameStruct, forKey: "packName")
historyClass.add(initialDataArray[0].partIdStruct, forKey: "packId")
historyClass.add(initialDataArray[0].partNameStruct, forKey: "partName")
historyClass.add(initialDataArray[0].partIndexStruct, forKey: "partIndex")
print(historyClass)
PFObject.pinAll(inBackground: [historyClass])
}
} // query
}
On Parse I have users with Facebook profile and Email login profile. So I want to bury for users data in my twitter-like app.
In my "messages" class on Parse I have column "sender" that contains pointers to parse users.
I just want to retrive and show the name of users in class "messages" contained in the column "sender" wich contains pointers to PFUsers of which I need data for keys
"first_name"
"last_name"
"profile_picture"
How can I retrive their data like name and image in order to show them in a tableview?
these are the declarations of my arrays:
var sendersArray : [String] = []
var picturesArray : [NSData] = []
maybe I could use something like this tuple, but I can't understand how to grab data from pointers
for user in list {
let firstName = "fist_name"
let lastName = "last_name"
let oProfileImage = NSData() //"image_profile" as! NSData
otherUsers.append((oName: firstName, oLastName: lastName, oImageProfle: oProfileImage))
}
version - 1:
I started with printing the whole pf object
//******************************************************
func theSearch() {
let theSearchQuery = PFQuery(className: "Messages")
theSearchQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) -> Void in
for object in objects! {
let theName = object.sender!
print(object)
print(theName)
sendersArray.append(theName)
let profilePicture = object["profile_pic"] as! PFFile
picturesArray.append(profilePicture)
}
self.tableView.reloadData()
})
}
//*******************************************************
version - 2:
then, found this solution, but still, doesn't
func theSearch() {
let theSearchQuery = PFQuery(className: "Messages" )
theSearchQuery.includeKey("sender")
theSearchQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) -> Void in
for object in objects! {
let theName = object.sender!["first_name"] as? String
print(object)
print(theName)
sendersArray.append(theName)
let profilePicture = object["profile_pic"] as! PFFile
picturesArray.append(profilePicture)
}
self.tableView.reloadData()
})
}
errors:
seems to be a problem with sender, maybe I shouldn't use it
thanks in advance
let theName = object.objectForKey("sender")!.objectForKey("first_name") as! String
Complete Code:
func theSearch() {
let theSearchQuery = PFQuery(className: "Messages")
theSearchQuery.includeKey("sender")
theSearchQuery.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) -> Void in
for object in objects! {
let theName = object.objectForKey("sender")!.objectForKey("first_name") as! String
print(object)
print(theName)
self.sendersArray.append(theName)
let profilePicture = object["profile_picture"] as! PFFile
self.picturesArray.append(profilePicture)
}
self.tableView.reloadData()
})
}
Also, your picturesArray should be of type PFFile, like this:
var picturesArray = [PFFile]()
NOT NSData. change that at the top of your class.
-----EDIT------:
If you want to retrieve an image from a parse query, do this:
1) at the top of your class, declare the following arrays to store the results:
// your images will be stored in the file array
var fileArray = [PFFile]()
// your first and last names will be stored in String Arrays:
var firstNameArray = [String]()
var lastNameArray = [String]()
2) perform the query:
let query1 = PFQuery(className: "_User")
query1.orderByDescending("createdAt")
query1.findObjectsInBackgroundWithBlock({
(objects : [AnyObject]?, error : NSError?) -> Void in
if error == nil {
for x in objects! {
let firstName = x.objectForKey("first_name") as! String
let lastName = x.objectForKey("last_name") as! String
self.firstNameArray.append(firstName)
self.lastNameArray.append(lastName)
if x.objectForKey("profile_picture") as? PFFile == nil {
print("do nothing cause it's nil")
}
else {
let file:PFFile = x.objectForKey("profile_image") as! PFFile
self.fileArray.append(file)
}
}
self.tableView.reloadData()
}
})
Note I am using Swift 2 and Xcode 7. Syntax is slightly different in Xcode 6.4 and Swift 1.2.
I have cloud code to search for the users relations with other users when they go to their friends page.
Problem I am having is populating the array of PFObjects I have that stores the info of the users friends so it can be displayed in the tableview.
Here is my cloud code:
Parse.Cloud.define("getFriends", function(request, response) {
var userId = request.params.UserKey;
var query = new Parse.Query(Parse.User);
query.get(userId, {
success: function(foundCurrentUser) {
var currentUser = foundCurrentUser;
var relation = currentUser.relation("Friends");
var getRelationQuery = relation.query();
getRelationQuery.find().then(function(results){
response.success(results);
});
},
error: function(error) {
response.error(error);
}
});
});
I check my logs and get the correct response. It contains the correct data in JSON.
Now here is the problem. My cloud query in the iOS app is what is causing me grief.
let currentUser: PFUser = PFUser.currentUser()!
let params = NSMutableDictionary()
params.setObject(PFUser.currentUser()!.objectId!, forKey: "UserKey")
PFCloud.callFunctionInBackground("getFriends", withParameters: params as [NSObject : AnyObject], block: {
(object:AnyObject?, error: NSError?) -> Void in
if error == nil {
self.currentUserFriendList.append(object as! PFObject)
}
else
{
println("didnt retrieve the carpoolers")
}
})
On the line of code I get an issue is self.currentUserFriendList.append(object as!! PFObject) with the error Could not cast value of type '__NSArrayM' (0x111cd8448) to 'PFObject' (0x10fd8a818).
I want to use a
for object in objects {
self.currentUserFriendList.append(object as! PFObject)
}
But the block isn't an object:[AnyObject]
When I print the object I get the correct relations wrapped in an Optional like so
Optional((
"<PFUser: 0x7fa5db4a6de0, objectId: 1FLleawAQz, localId: (null)> {\n Friends = \"<PFRelation: 0x7fa5db47b1a0, 0x0.(null) -> _User>\";\n email = \"test#test.com\";\n fullName = \"Tester \";\n profilePicture = \"<PFFile: 0x7fa5db4a0140>\";\n username = \"test#test.com\";\n}",
"<PFUser: 0x7fa5db47d5f0, objectId: nqFBQYIVjD, localId: (null)> {\n Friends = \"<PFRelation: 0x7fa5db5c97b0, 0x0.(null) -> _User>\";\n email = \"test2#test.com\";\n fullName = test2;\n profilePicture = \"<PFFile: 0x7fa5db554400>\";\n username = \"test2#test.com\";\n}"
))
I was able to get the response to output exactly what I wanted and append it to my array of PFObjects like this.
if error == nil {
let objects = response as! [PFObject]
for object in objects as [PFObject] {
self.currentUserFriendList.append(object as PFObject)
println("\(object)")
}
I am retrieving the current user info from parse and saving it in data:NSMutableArray = NSMutableArray() and tring to get the "fullName" of the user to show it in label called userName I'm using this :
var name:String = self.data["fullName"] as! String // error here: AnyObject is not convertible String.
self.userName.text = name
I saw many question in here but they dint help me. Gave the same error.
println(self.data) gave me this :
(
"<PFUser: 0x7fa01bd7eed0, objectId: SiA72FwNi2, localId: (null)> {\n email = \"jhsbdfjhs#jhbs.com\";\n fullName = \"Khjdf Ujhdsf\";\n gender = male;\n profilePicture = \"<PFFile: 0x7fa01bd719b0>\";\n username = jhsfgj;\n}"
)
this is my function:
func loadData() {
if PFUser.currentUser() != nil {
PFUser.currentUser()!.fetchIfNeededInBackgroundWithBlock({ (user: PFObject?, error: NSError?) -> Void in
if user != nil {
var u = user as! PFUser
self.data.addObject(u)
}
})
println(self.data)
}
}
your self.data is NSMutableArray and you can not access fullName like this, first you need to get PFObject from self.data by giving index like this self.data[0] and then get fullName
var object:PFObject = self.data[0]
var st:String = object["fullName"] as! String