AFHTTPRequestOperationManager UI Frozen with Swift - asynchronous

I have one question, I'm doing a short example with AFNetworking and Swift and I'm seeing that my UI is frozen while data is being dowloaded.. is it normal?
This is my code
import UIKit
class ViewController: UIViewController {
var manager:AFHTTPRequestOperationManager = AFHTTPRequestOperationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func getJSON(sender : AnyObject) {
manager.GET("https://itunes.apple.com/es/rss/topfreeapplications/limit=10/json", parameters: nil,
success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
println("JSON: \(responseObject.description)")
},
failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
println("Error: \(error.localizedDescription)")
})
}
}

Related

After logging in once, when you close and open the application, it does not log out. swiftui

import Firebase
#main
struct PaslaApp: App {
//#UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate: AppDelegate
#StateObject var usersinfo=UsersInfoModel()
#Environment(\.scenePhase) var scenePhase
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
HomeView()
}
.onChange(of: scenePhase) { newScenePhase in
switch newScenePhase {
case .active:
print("App is active")
case .inactive:
print("App is inactive")
case .background:
print("App is in background")
#unknown default:
print("Oh - interesting: I received an unexpected new value.")
}
}
}
}
I want to get data from firebase and start it on different screens according to availability, but I can't. I'm getting the error "please call firebaseapp.configure() before using firestore".
Please Help!
I need to write the code I wrote in appDelegate before swiftUI here.
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
FirebaseApp.configure()
let currentUser=Auth.auth().currentUser
let firebaseDatabase=Firestore.firestore()
var userTypeArray=[String]()
var stadiumTypeArray=[String]()
if currentUser != nil {
firebaseDatabase.collection("Users").addSnapshotListener { (snapshot, error) in
if error == nil {
for document in snapshot!.documents{
if let userType=document.get("User") as? String{
userTypeArray.append(userType)
if userTypeArray.contains(currentUser!.uid) {
firebaseDatabase.collection("Users").whereField("User", isEqualTo: currentUser!.uid).addSnapshotListener { (snapshot, error) in
if error == nil {
for document in snapshot!.documents {
if let userName=document.get("Name") as? String{
if userName == "" {
let board=UIStoryboard(name: "Main", bundle: nil)
let userInfo=board.instantiateViewController(withIdentifier: "userInfo")
self.window?.rootViewController=userInfo
} else {
let board=UIStoryboard(name: "Main", bundle: nil)
let userInfo=board.instantiateViewController(withIdentifier: "userProfile") as! UITabBarController
self.window?.rootViewController=userInfo
}
}
}
}
}
}
}
}
}
}
return true
}

SwiftUI - Button - How to pass a function request to parent

How can I have a button perform an action which triggers a function in its 'parent' view? I'm trying to refactor my code so that components are as small as possible.
In this case, the button performs a few tasks, but one of them is to run a function:
Button(
action: {
self.setViewBackToNil()
}){
Text("Button")
}
// which triggers a function
func setViewBackToNil(){
self.userData.image = nil
self.isProcessing = false
.... etc
}
Now, if I turn the button into its own view, I can't pass self.setViewBackToNil because it's contained within the struct of the parent.
Is there a way for a component to trigger a function within its parent?
The best examples on closures and how they can be used is found in the official swift documentation.
This is a small example on how to pass a closure to your child view which then calls a function of the parent:
struct ChildView: View {
var function: () -> Void
var body: some View {
Button(action: {
self.function()
}, label: {
Text("Button")
})
}
}
struct ParentView: View {
var body: some View {
ChildView(function: { self.fuctionCalledInPassedClosure() })
}
func fuctionCalledInPassedClosure() {
print("I am the parent")
}
}
I hope this helps!
Pass a function
And here is an example to pass the function:
struct ChildView: View {
var function: () -> Void
var body: some View {
Button(action: {
self.function()
}, label: {
Text("Button")
})
}
}
struct ParentView: View {
var body: some View {
ChildView(function: self.passedFunction)
}
func passedFunction() {
print("I am the parent")
}
}
Pass a function with parameters
struct ChildView: View {
var myFunctionWithParameters: (String, Int) -> Void
var body: some View {
Button(action: {
self.myFunctionWithParameters("parameter", 1)
}, label: {
Text("Button")
})
}
}
struct ParentView: View {
var body: some View {
ChildView(myFunctionWithParameters: self.passedFunction)
}
func passedFunction(myFirstParameter: String, mySecondParameter: Int) {
print("I am the parent")
}
}

Use a button to play a video in xcode 10

to be honest i dont quite understand what I'm doing here is the code that I tried to use to play the video it builds okay but when i press the button i get a "sigabrt" warning and it doesnt work.
here's the code:
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func VideoPlayer(_ sender: Any) {
guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.player = player
present(playerController, animated: true) {
player.play()
}
}
}
}
Try this.
import UIKit
import AVKit
class ViewController: UIViewController {
var avPlayer: AVPlayer!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func VideoPlayer(_ sender: Any) {
playVideo()
}
func playVideo() {
let filepath: String? = Bundle.main.path(forResource: "videoplayback", ofType: "mp4")
let fileURL = URL.init(fileURLWithPath: filepath!)
avPlayer = AVPlayer(url: fileURL)
let avPlayerController = AVPlayerViewController()
avPlayerController.player = avPlayer
avPlayerController.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
// Turn on video controlls
avPlayerController.showsPlaybackControls = true
// play video
avPlayerController.player?.play()
self.view.addSubview(avPlayerController.view)
self.addChild(avPlayerController)
}
}

Value of type 'AuthDataResult' has no member 'uid'

I am a noob trying to create a social app through Youtube videos, and I am following instructions of this video.
https://youtu.be/GrRggN41VF0
At around 3 mins. of the video you'll see the code.
Here's the code I have.
import UIKit
import Firebase
import SwiftKeychainWrapper
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var userImgView: UIImageView!
#IBOutlet weak var usernameField: UITextField!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
override func viewDidLoad() {
emailField.delegate = self
passwordField.delegate = self
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
if let _ = KeychainWrapper.standard.string(forKey: "uid") {
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == emailField {
passwordField.becomeFirstResponder()
} else if textField == passwordField {
textField.resignFirstResponder()
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func signInPressed(_ sender: Any) {
if let email = emailField.text, let password = passwordField.text {
Auth.auth().signIn(withEmail: email, password: password) { (user, error) in
if error != nil {
// Create Account
} else {
if let userID = user?.uid {
KeychainWrapper.standard.set((userID), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
}
}
}
}
Screenshot of the error
What am I doing wrong here and how do I fix this?
Try using:
if let user = Auth.auth().currentUser, let uid = user?.uid {
KeychainWrapper.standard.set((uid), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
Try using with the guard statement to unwrap optionals safely. Give it a try!
guard let uid = user?.uid else { return }
KeychainWrapper.standard.set((uid), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
or
guard let uid = Auth.auth().currentUser?.uid else { return }
KeychainWrapper.standard.set((uid), forKey: "uid")
self.performSegue(withIdentifier: "toFeed", sender: nil)
I hope this helps you..

Asynchronous Request (Order Matters)

I'm using Alamofire to execute a number of asynchronous requests concurrently, and SwiftyJSON to handle the response.
I need help making sure that appending to moviesByCategory occurs in order.
For example, the "top_rated" data response should be the first element appended to moviesByCategory, not "upcoming".
var moviesByCategory = [[JSON]]()
override func viewDidLoad() {
super.viewDidLoad()
let apiEndPoints = ["top_rated", "popular", "now_playing", "upcoming"]
let dispatchGroup = DispatchGroup()
for endPoint in apiEndPoints {
let endPointURL = URL(string: "https://api.themoviedb.org/3/movie/\(endPoint)?api_key=\(apiKey)&language=en-US&page=1")!
dispatchGroup.enter()
getMoviesFromEndPoint(url: endPointURL)
}
dispatchGroup.notify(queue: DispatchQueue.main) {
self.tableView.reloadData()
}
}
func getMoviesFromEndPoint(url: URL, group: dispatchGroup) {
Alamofire.request(url).responseData { response in
if let data = response.result.value {
let json = JSON(data: data)
self.moviesByCategory.append(json["results"].arrayValue)
}
}
}
The purpose for DispatchGroup is to reload the UITableView once all requests have completed.
Any help with this would be tremendously appreciated. Please do point out where I am wrong.
Add a completion handler parameter to getMoviesFromEndPoint:
func getMoviesFromEndPoint(url: URL, completion: () -> Void) { ... }
and leave the group within after the network call completed:
getMoviesFromEndPoint(url: endPointURL) {
dispatchGroup.leave()
}
Complete code:
override func viewDidLoad() {
super.viewDidLoad()
let apiEndPoints = ["top_rated", "popular", "now_playing", "upcoming"]
let dispatchGroup = DispatchGroup()
for endPoint in apiEndPoints {
let endPointURL = URL(string: "https://api.themoviedb.org/3/movie/\(endPoint)?api_key=\(apiKey)&language=en-US&page=1")!
dispatchGroup.enter()
getMoviesFromEndPoint(url: endPointURL) {
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: DispatchQueue.main) {
self.tableView.reloadData()
}
}
func getMoviesFromEndPoint(url: URL, completion: () -> Void) {
Alamofire.request(url).responseData { response in
if let data = response.result.value {
let json = JSON(data: data)
self.moviesByCategory.append(json["results"].arrayValue)
}
completion()
}
}

Resources