I Cannot Access My Array Objects Anywhere, How to Access Them in Swift

I cannot access my array objects anywhere, how can I access them in swift?

Data is loaded from Firebase asynchronously. While you may store it in variables that can be accessed from anywhere, the timing matters.

In your code, when the print(self.arr) runs, the self.arr.append(...) hasn't run yet. You can most easily see this by placing breakpoints on these lines and running the code in a debugger, or by placing some logging code and checking its output.

For this reason, all code that needs data from the database needs to be inside the completion handler or be called from there.

For some more on this, and examples of solutions, see:

  • Code not finishing the function, it is ending execution halfway through, which in turn includes more links
  • Make code with Firebase asynchronous
  • Why isn't my function that pulls information from the database working?, which even more links
  • Finish all asynchronous requests before loading data?, using a dispatch group
  • Asynchronous Swift call into array
  • using variables outside of completion block
  • wait for two asynchronous completion functions to finish, before executing next line code
  • Finish all asynchronous requests before loading data?

why I can't access my 3rd level CoreData data in swift?

The temas property is a NSOrderedSet, and the subscript [0] returns the
type AnyObject. So (as already said in a comment) you have to cast the AnyObject
to the actual type

let curso = cursos[index]
println(curso.nombre)
let firstTema = curso.temas[0] as Tema
println(firstTema.nombre)
let firstSubTema = firstTema.subTemas[0] as SubTema
println(firstSubTema.nombre)

Note that you can simplify your loop using for - in:

for curso in cursos {
// ...
}

and recursively enumerating all objects would look like

for curso in cursos {
println(curso.nombre)

for tema in curso.temas.array as [Tema] {
println(tema.nombre)

for subtema in tema.subTemas.array as [SubTema] {
println(subtema.nombre)
}
}
}

using variables outside of completion block

The entire purpose of the completion parameter of userBinfo is to provide a mechanism for being informed when the asynchronous observeEventType is called. So put code contingent upon the completion of that asynchronous method inside the userBinfo { user in ... } closure.

And if part of the UI doesn't make sense until that asynchronous completion closure is called, then have viewDidLoad configure the UI to make that explicit (perhaps show a UIActivityIndicatorView or whatever) and then remove that stuff inside the completion handler.

override func viewDidLoad() {
super.viewDidLoad()

// do whatever you want to let the user know that something asynchronous
// is happening, e.g. add a spinning `UIActivityIndicatorView` or whatever

userBinfo { user in
self.userBinfos = user

// Update the UI here, including removing anything we presented to let
// the user know that the asynchronous process was underway. If you were
// dealing with UITableView`, you'd call `tableView.reloadData()` here.
}

// but not here
}

Can't access decoded JSON data (from API) outside the URLSession data task Function Scope

As you already have a completion handler use it and pass the received data

func getJSON(completed: @escaping ([API_data]) -> Void) {

let url = "URL Here" // I have the original URL here, which I can't shar
let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _ , error in

if let error = error { print(error); return }

do {
completed(try JSONDecoder().decode([API_data].self,from:data!))
} catch{
print(error)
}
}
task.resume()
}

and use it

getJSON { apiData in 
print(apiData[0].id) // This prints my data
}

Or more comfortable with the Result type

func getJSON(completed: @escaping (Result<[API_data],Error>) -> Void) {

let url = "URL Here" // I have the original URL here, which I can't shar
let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _ , error in

if let error = error { completed(.failure(error)); return }
Result { try JSONDecoder().decode([API_data].self,from: data!) }
}
task.resume()
}

getJSON { result in
switch result {
case .success(let apiData): print(apiData[0].id) // This prints my data
case .failure(let error): print(error)
}

}

Why I can't use variable that I defined in viewDidLoad in swift 3

The issue is you cannot access instance property when you initialized another another property outside any method because complier don't know which one initialized the first, so what you need to do is declare headerList simply set the account string only as first object of array and latter changed it with new value.

var userAccountMoney = String()
var headerList = ["account" , "Help" , "" ]

Now in viewDidLoad simply replace the first object with new value.

override func viewDidLoad() {
super.viewDidLoad()

let userAccount = profileViewController().userMoney

let numberFormatter = NumberFormatter()
numberFormatter.locale = Locale(identifier: "fa")
numberFormatter.numberStyle = NumberFormatter.Style.decimal
numberFormatter.string(from: NSNumber(value: userAccount))
userAccountMoney = numberFormatter.string(from: NSNumber(value: userAccount))!
self.headerList[0] = "account\(userAccountMoney)"
}

Asynchronous Swift call into array

func fetchUser(_ completion:@escaping ([noteClass] , _ success: Bool)-> Void){
let coordinotes = [noteClass]()

FIRDatabase.database().reference().child("notes").observe(.childAdded, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = noteClass(dictionary: dictionary)
coordinotes.append(user)
}
completion(coordinotes, true)
}, withCancel: nil)

}

and then you call it in viewDidLoad like this:

  fetchUser { (coordinotes, success) in
if success {
self.coordinotes = coordinote
self.loadAllCoordinotes()
}
}

Passing Data Indirectly to an Unrelated NSViewController

With the caveat that "globals and singletons should be avoided," it sounds like they are a good fit for what you're trying to do. As you get more comfortable in Cocoa you can move into more sophisticated means of accomplishing this (dependency injection). Look into this as you get more comfortable with Cocoa.

Create a simple singleton type:

// AppState.swift

class AppState {
// Basic singleton setup:
static let shared = AppState()
private init() {} // private prevents instantiating it elsewhere

// Shared state:
var carrierArray: [String] = []
}

Access it from your view controllers:

// YourViewController.swift:

@IBAction func doSomething(_ sender: Any) {
AppState.shared.carrierArray = ...
}

If you need to update the other view controllers when this shared state changes, notifications are a good tool for that. You could do this with a didSet on carrierArray, or simply trigger the notification manually.



Related Topics



Leave a reply



Submit