I can't understand what is wrong with this function:
var arrayStatusUserTable:[String] = [String]()
var statusText:String = String()
func retrieveStatusInTable(name: String) -> String {
var statusFinal:String = String()
var query:PFQuery = PFQuery(className: "Status")
query.whereKey("NameCreator", equalTo: name)
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
for phrase in objects! {
let phraseTakenParse:String? = (phrase as! PFObject)["Status"] as? String
if phraseTakenParse != nil {
self.arrayStatusUserTable.append(phraseTakenParse!)
}
}
// Take the last status
if var frase = self.arrayStatusUserTable.last {
var lastFraseStatus:String = frase //self.arrayStatusUtente.last!
self.statusText = lastFraseStatus
statusFinale = lastFraseStatus
return statusFinale
}
}
}
This one return the error: 'String' is not convertible to 'Void'! I just wanna return the last object from the array filled from Parse! Thanks for helping me!
return statusFinale written in blocks, so retrieveStatusInTable function return Void.
When you use asynchronous method, set function return type "Void" and tell result with blocks (completionHandler).
Sample Code:
func retrieveStatusInTable(name: String, completionHandler:((statusFinale: String) -> Void)) {
// .....
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
// ........
statusFinale = lastFraseStatus
completionHandler(statusFinale: statusFinal)
}
}
Usage:
retrieveStatusInTable("Sample", { (statusFinale) -> Void in
println(statusFinale)
})
Related
I am looking to create a dictionary that will have
let urlDict:[String:Func] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]
func getLoginURL() -> String{
if (sandbox == true){
return sb_login_url
}else{
return live_login_url
}
}
func getResetPasswordURL() -> String{
if (sandbox == true){
return sb_reset_url
}else{
return live_reset_url
}
}
The purpose of this dict is to get/map functions based on the KEY and as per KEY corresponding function must be called which in turn will return return urls.
I have tried naming the dictionary but I am unable to do it
let urlDict:[String:Func] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]
let urlDict:[String:Function] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]
let urlDict:[String:Functions] = ["LOGIN":getLoginURL(), "RESET":getResetPasswordURL()]
EDIT 1
class Constants{
private let sb_login_url = "http://IP_ADDRESS_COM/login_with_credentials"
private let live_login_url = "http://google.com"
private let sb_reset_url = "http://IP_ADDRESS_COM/forgot_password"
private let live_reset_url = "http://google.com"
func getLoginURL() -> String{
if (sandbox == true){
return sb_login_url
}else{
return live_login_url
}
}
func getResetPasswordURL() -> String{
if (sandbox == true){
return sb_reset_url
}else{
return live_reset_url
}
}
` let urlDict: [String: () -> String] = ["LOGIN": Constants.getLoginURL(), "RESET":Constants.getResetPasswordURL()]
if let getFunc = urlDict[url_key] {
let url = (getFunc()) // foo}
}
You must specify the type of the functions (which are common for both getLoginURL and getResetPasswordURL) for the value slot in the dictionary, namely () -> String, a zero-arguments function returning a String instance.
func getLoginURL() -> String {
return "foo"
}
func getResetPasswordURL() -> String {
return "bar"
}
let urlDict: [String: () -> String] =
["LOGIN": getLoginURL, "RESET":getResetPasswordURL]
/* ^^^^^^^^^^^- note that you do not _call_ the functions,
as this would result in a String instance */
// get a function reference from the dictionary and invoke it
if let getFunc = urlDict["LOGIN"] {
print(getFunc()) // foo
}
After your comments below, as well as your edit, it seems you want the get... functions to be class members if your class Constants (i.e., marked static).
class Constants {
static var sandbox = true
// I've just added this to test your example
private static let sb_login_url = "http://IP_ADDRESS_COM/login_with_credentials"
private static let live_login_url = "http://google.com"
private static let sb_reset_url = "http://IP_ADDRESS_COM/forgot_password"
private static let live_reset_url = "http://google.com"
static func getLoginURL() -> String {
if (Constants.sandbox == true){
return Constants.sb_login_url
}
else {
return Constants.live_login_url
}
}
static func getResetPasswordURL() -> String{
if (Constants.sandbox == true){
return Constants.sb_reset_url
}
else {
return Constants.live_reset_url
}
}
}
let urlDict: [String: () -> String] =
["LOGIN": Constants.getLoginURL, "RESET": Constants.getResetPasswordURL]
// get a function reference from the dictionary and invoke it
if let getFunc = urlDict["LOGIN"] {
print(getFunc()) // http://IP_ADDRESS_COM/forgot_password
Constants.sandbox = false
print(getFunc()) // http://google.com
}
You could simply create a global typealias to Function prototype and can use it anywhere in your project and you don't need to use () -> String everytime when you create Dictionary.
public typealias VoidToStringFunction = () -> String
func getLoginURL() -> String {
return "url"
}
func getResetPasswordURL() -> String {
return "password"
}
and use it like this
let urlDict : [String: VoidToStringFunction] = ["LOGIN": getLoginURL, "Password": getResetPasswordURL]
I keep getting this error when trying to update a PFObject '[Error]: No results matched the query. (Code: 101, Version: 1.12.0)' here is my code:
let userQuery = PFQuery(className: "User")
userQuery.getObjectInBackgroundWithId("cE3DE48Fa9") {
(userQueryObject: PFObject?, error: NSError?) -> Void in
if error != nil {
print(error)
}
else if let userQueryObject = userQueryObject {
userQueryObject["House_Motto"] = self.campaignMottoTextBox.text
userQueryObject.saveInBackground()
} }
What do I do?
Here is my new code:
currentUser!.setObject(self.campaignMottoTextBox.text!, forKey: "House_Motto")
Here is an example of how to use PFUser.query() to query the user class in parse, note my example uses findObjectsInBackgroundWithBlock(), rather than getObjectsInBackgroundWithId()
var userData1 = [String]()
var userData2 = [Double]()
var allUsers = [PFUser]()
func fetchUserData() {
let userQuery: PFQuery = PFUser.query()!
userQuery.orderByAscending("username")
userQuery.whereKey("username", notEqualTo: (currentUser?.username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var userData = users!
if error == nil {
if userData.count >= 1 {
for i in 0...users!.count-1 {
self.userData1.append(userData[i].valueForKey("columnNameInParse1") as! String)
self.startTimes.append(userData[i].valueForKey("ColumnNameInParse2") as! Double)
}
}
self.allUsers = users as! [PFUser]
self.tableView.reloadData()
} else {
print(error)
}
})
}
and in order to update a value for a given user you will do...
func updateObjectInParse(){
currentUser?.setObject(campaignMottoText.text, forKey: "columnNameInParse")
currentUser?.saveInBackground()
}
where "columnNameInParse" is the name of the column for the object of which you want to update in parse. This is case sensitive. And currentUser is the PFUser.currentUser
func getParse (className:String,key:String,dataName:AnyObject) -> (String)
{
var result = String()
var query = PFQuery(className: className)
query.whereKey(key, equalTo: dataName)
query.findObjectsInBackgroundWithBlock{
(objects, error) -> Void in
if error == nil {
println("Found")
if let objects = objects as? [PFObject] {
for object in objects {
result = object[key] as! String
}
}
} else {
println("Error \(error) \(error!.userInfo!)")
}
}
return result
}
This is my function that can getting data from my class in parse database. I want to return that data in String but it returned nothing when I try to printed it.
Thank you for every comments.
You are using an asynchronous call. You need to use findObjects(), but this will stay on the main thread. Why do you need to return a string? You could set a variable from within the completion block that could update a label on your view or something like that.
Edit: Since you are trying to set a label, you don't need to return the string, you should just set the label from within your completion block. This would modify you're given code as follows:
func getParse (className:String,key:String,dataName:AnyObject)
{
var result = String()
var query = PFQuery(className: className)
query.whereKey(key, equalTo: dataName)
query.findObjectsInBackgroundWithBlock{
(objects, error) -> Void in
if error == nil {
println("Found")
if let objects = objects as? [PFObject] {
for object in objects {
// result = object[key] as! String
self.textLabel.text = result // NEW CODE HERE
}
}
} else {
println("Error \(error) \(error!.userInfo!)")
}
}
}
func retrieveMessages() {
var query:PFQuery = PFQuery(className: "Message")
//Call findobjectsinbackground
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
self.messagesArray = [String]()
for messageObject in objects { <<<<<<<<<<<<<<<<< error
let messageText:String? = (messageObject as PFObject)["Text"] as? String
if messageText != nil {
self.messagesArray.append(messageText!)
}
}
self.messageTableView.reloadData()
}
}
From this code an error occurs saying: [AnyObject]? does not have a member named 'Generator'. Is there a way how to correct this?
Your objects array is declared as an Optional : objects:[AnyObject]?
So you need to unwrap it before looping over it:
for messageObject in objects! {
// do stuff
}
And since objects can be nil, better do this:
if let myObjects = objects {
for messageObject in myObjects {
// do stuff
}
}
That's because it is an optional array. Simply wrap it around if let and you'll be fine.
In playground:
func retrieveMessages(objects:[AnyObject]?) {
var messagesArray = [String]()
if let objs = objects {
for messageObject in objs {
let messageText:String? = "test"
if messageText != nil {
messagesArray.append(messageText!)
}
}
}
}
In your case, the complete code would be:
func retrieveMessages() {
var query:PFQuery = PFQuery(className: "Message")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
self.messagesArray = [String]()
if let objs = objects {
for messageObject in objs {
let messageText:String? = (messageObject as PFObject)["Text"] as? String
if messageText != nil {
self.messagesArray.append(messageText!)
}
}
}
self.messageTableView.reloadData()
}
}
Since your objects Array is of [AnyObject]?, before using them you need to do below step.
if let myObjects = objects as? [PFObject] {
//Do the things...
}
[AnyObject]? it´s an optional array.
You must unwrap it before using it.
if let objects = objects
{
for messageObject in objects
{
....
}
}
The problem I'm having on this request is the first function syncRequest always returns nil since the function exits before the (reply, error) comes back to fill out my return dictionary.
Is there a way for it to wait for the callback to return before returning out of my closure?
public typealias KKWatchSyncResponse = Dictionary<String, AnyObject>
func syncRequest() -> KKWatchSyncResponse? {
var syncResponseDict : KKWatchSyncResponse?
createRequest(KKWatchRequest.Sync, parameter: nil) { reply, error in
if reply == nil || error != nil {
return
} else {
syncResponseDict = KKWatchSyncResponse()
}
if let songInfo = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["songInfo"] as NSData) as NSDictionary? {
syncResponseDict!["songInfo"] = songInfo
}
if let albumArtImage = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["albumArt"] as NSData) as? UIImage {
syncResponseDict!["albumArtImage"] = albumArtImage
}
if let isPlaying = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["isPlaying"] as NSData) as? Bool {
syncResponseDict!["isPlaying"] = isPlaying
}
}()
return syncResponseDict
}
func createRequest(request:KKWatchRequest, parameter: KKWatchAPIRequestParameter?, callback:KKWatchAPICallback) -> KKWatchAPIParentRequest {
var requestDict : Dictionary<String, AnyObject> = [KKBOXWatchAppRequestType : request.rawValue]
if parameter != nil {
requestDict += parameter! //Combine 2 dictionaries
}
return { WKInterfaceController.openParentApplication(requestDict){ reply, error in
callback(reply, error)
}
}
}
Your help us much appreciated!
Could you have syncRequest() take a closure that gets called with the results when ready? Change the definition to something like:
func syncRequest(callback:(KKWatchSyncResponse?)->Void) { ... }
Then at the end of your createRequest() call, you could call the callback on syncResponseDict, since now it's been populated with your data... callback(syncResponseDict).
EDIT: Here's the solution I had in mind.
func syncRequest(callback:(KKWatchSyncResponse?)->Void) {
createRequest(KKWatchRequest.Sync, parameter: nil) { reply, error in
if reply == nil || error != nil {
callback(nil)
} else {
var syncResponseDict : KKWatchSyncResponse? = KKWatchSyncResponse()
if let songInfo = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["songInfo"] as NSData) as NSDictionary? {
syncResponseDict!["songInfo"] = songInfo
}
if let albumArtImage = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["albumArt"] as NSData) as? UIImage {
syncResponseDict!["albumArtImage"] = albumArtImage
}
if let isPlaying = NSKeyedUnarchiver.unarchiveObjectWithData(reply!["isPlaying"] as NSData) as? Bool {
syncResponseDict!["isPlaying"] = isPlaying
}
callback(syncResponseDict)
}
}()
}
It is straight forward to implement a locking variable. This is most helpful for unit tests that do some async network loading.
func waitingFunction()
{
//set a lock during your async function
var locked = true
RunSome.asyncFunction() { () -> Void in
//after your sync function remove the lock
locked = false
})
//wait for the async method to complete before advancing
while(locked){wait()}
//move on from the lock
doMoreStuff()
}
func wait()
{
NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: 1))
}