Function that returns an array - swift

I'm trying to get an array to return from a function I call but the return optionArray in the below code give me a "Use of unresolved identifier optionArray.
public func getAdminSites(){
let getSiteData = UserDefaults.standard.object(forKey: "adminSites")
if getSiteData != nil
{
do {
guard let sitesData = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(getSiteData as! Data) as? [ModelSites] else {
fatalError("loadWidgetDataArray - Can't get Array")
}
var optionArray = ["All sites"]
for i in 0...sitesData.count-1 {
optionArray.append(sitesData[i].name)
}
} catch {
fatalError("loadWidgetDataArray - Can't encode data: \(error)")
}
}
return optionArray
}

There are two errors:
Function definition is missing a return type
OptionArray (stored variable) is declared in a control flow if scope and not accessible on a function body level
When you define a function, you can optionally define one or more
named, typed values that the function takes as input, known as
parameters. You can also optionally define a type of value that the
function will pass back as output when it is done, known as its return
type.
source
Fixed code:
public func getAdminSites() -> [String] {
let getSiteData = UserDefaults.standard.object(forKey: "adminSites")
var optionArray = [String]()
if getSiteData != nil
{
do {
guard let sitesData = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(getSiteData as! Data) as? [ModelSites] else {
fatalError("loadWidgetDataArray - Can't get Array")
}
optionArray = ["All sites"]
for i in 0...sitesData.count-1 {
optionArray.append(sitesData[i].name)
}
} catch {
fatalError("loadWidgetDataArray - Can't encode data: \(error)")
}
}
return optionArray
}

Related

Swift - Can I read the value of a enum as an optional without doing a switch?

Does Swift have a syntax similar to case .enumCase(let value) = enum that can be used as a one liner to read the enum as a specific case, or a nil
For instance with a Swift.Result instead of
let error: Error?
if case let .failure(value) = result {
error = value
} else {
error = nil
}
can I write something as
case let .failure(error) = result // Well this I can't
let error = result.as(.failure)
To simplify working with Result (or other enums) you can use next extension:
extension Result {
var value: Success? {
if case let .success(value) = self {
return value
}
return nil
}
var error: Failure? {
if case let .failure(error) = self {
return error
}
return nil
}
}
Then you can get optional values in single line:
let value = result.value
let error = result.error
if let value = result.value {
print(value)
}
if let error = result.error {
print(error)
}

How do I extract firebase functions to an object in Swift?

I'm new to object oriented programming and am trying to move logic out of my view controller and into its own model so I can reuse endpoint calls and such, but I can't figure out how to alert my view controller that the result has occurred from within the object. Within javascript, I'd normally just set the function to return a value but it is not allowing me to return anything other than Void Cannot convert return expression of type 'Void' to return type 'String'.
import Foundation
import Firebase
class CloudFunctions {
let functions = Functions.functions()
func addNewAccount(param1: String) -> String {
functions.httpsCallable(FunctionsConstants.myFunction).call(["param1Name":param1]) { (result, error) in
if let e = error {
return "\(e)"
} else {
if let result = result {
return "\(result.data)"
} else {
return "Sorry, we couldn't unwrap the result."
}
}
}
}
}
and in my view controller I'm calling it like
let cloudFunctions = CloudFunctions()
self.result = cloudFunctions.addNewAccount(param1: dataHere)
I thought I might be able to create a didSet on result to update the UI, but it won't let the function go through because I get the error: Cannot convert return expression of type 'Void' to return type 'String'
You need a completion
func addNewAccount(param1: String,completion:#escaping(String -> ())){
functions.httpsCallable(FunctionsConstants.myFunction).call(["param1Name":param1]) { (result, error) in
if let e = error {
return "\(e)"
} else {
if let result = result {
completion("\(result.data)")
} else {
completion("Sorry, we couldn't unwrap the result.")
}
}
}
}
addNewAccount(param1:"") { str in
}

Swift Firestore cannot get data to Object

Hello i try to parse a array of strings into a dao. To do so i created this:
func getUsersAbos(){
let userid = Auth.auth().currentUser?.uid
let docRef = db.collection("Users").document(userid!)
docRef.getDocument { (document, error) in
if let city = document.flatMap({
$0.data().flatMap({ (data) in
return UserBlogObject(channelAbos: data)
})
}) {
print("City: \(city)")
} else {
print("Document does not exist")
}
}
}
and here is my Dao:
import Foundation
class UserBlogObject{
var channelAbos = Any
init(channelAbos: [String]) {
self.channelAbos = channelAbos
}
init(){
}
}
i get an error at this line:
return UserBlogObject(channelAbos: data)
Cannot convert value of type '[String : Any]' to expected argument type '[String]'
please note that i want to download just an array inside the document, not the whole document.
You can do something like this. I don't think there is a need to overcomplicate the function with flatMap() but you can do it if you want. Here is a code example of how you could create your method.
func getUsersAbos() {
guard let userID = Auth.auth().currentUser?.uid else { return }
let docRef = db.collection("Users").document(userID)
docRef.getDocument { (document, error) in
if error != nil { return }
guard let data = document?.data() else { return }
guard let channelAbos = data["channelAbos"] as? [String] else { return }
let userBlogObject = UserBlogObject.init(channelAbos: channelAbos) // This is the created object. Handle it.
}
}
And your class:
class UserBlogObject {
var channelAbos : [String]
init(channelAbos: [String]) {
self.channelAbos = channelAbos
}
}

Swift check type of object

I want to compare types of objects in swift.
I've got a function which takes an object of NSError as parameter. It should return a custom string.
It looks like this:
static func getLocalizedErrorText(error: NSError) -> String{
switch error {
case is NoConnection: //class NoConnection: NSError
return "....."
...
}
But the function is not working as expected. I think the main problem is that this example is not working:
var dummy = MySubError() //class MySubError: MyBaseError
var dummy2: MyBaseError?
dummy2 = MySubError()
if dummy.dynamicType == MySubError.self {
//This will work
}
if dummy2.dynamicType == MySubError.self {
//This will not work
}
How can I check which type the parameter got?
You can check for a type using
if error is MySubError {
// do stuff
}
You can also do an optional cast, which will succeed, if the type matches or return nil, if not:
let subError = error as? MySubError
which you can also use in a guard predicate or if let statement:
if let subError = error as? MySubError {
// do stuff
}
or
guard let subError = error as? MySuberror else { return }

How can I return my string in swift by using parse?

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!)")
}
}
}