Show a loading animation with swift while waiting for the data from Parse - ios

I've browsed through many q&a-s here but almost all of them are way too specific for the use cases of other people.
My situation is more general and sort of simple:
iOS\Swift
I have a button which when clicked - moves the user to the next view.
At the same time as the button is clicked it also executes a query to Parse to fetch the data which will be displayed on the next view.
I'm using Parse's async query.getObjectInBackgroundWithId("jjjkkkdddd")
So if my code runs as is = click -> move to the next view -> empty
because fetching stuff takes a second or so.
What i want is to have a small animation popping up when user clicks a button to tell them that the data is being fetched at the moment and move to the next view once data arrives.
Here is my button tap code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "1") {
var svc = segue.destinationViewController as ViewControllerQuotes;
svc.toPass = functionToFetchDataFromParse() //<- takes longer than
//switching to the next view
//toPass is a var which lands into the next view
//and it's value is displayed to the user.
}
}
I am quite fresh with Swift and iOS dev so I can't figure this one out still:(

On the button tap just use addSubview() to add a UI element like UIActivityIndicatorView.
In the callback from Parse, remove the view and go to the next controller, calling the segue programatically.

SOLUTION FOR ME:
Ok i fiddled around and found the best way which suites me for now. what I do is from View1 the button is pressed and it tell the view controller of the 2-nd view to fire up the data fetching function.
In the 2-nd vie controller once it trigger the async function for retrieving data from Parse it also shows the activity indicator and make it run.
The user sees an empty screen with an activity spinner running. once the async function gets back the data it pushes it into a an empty label and shutsdown+hides the activity indicator.
Works great for my case. no interface hanging. and clear for the user about what's happening where and when.
Thanks to everyone!
p.s. this works for me because that's the end of the lifecycle for the retrieved data. if there were other functions depending on it - this wouldn't work:(

What about setting the object on the segue's destination View controller and then fetch the object, and then reload the view?
This would be:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "1") {
var svc = segue.destinationViewController as ViewControllerQuotes;
svc.yourObjectWhichIsToFetch = yourObjectWhichYouWantToPass //need to create a variable on the ViewControllerQuotes!
}
}
And then in the ViewControllerQuotes class:
class ViewControllerQuotes:ViewController {
var yourObjectWhichIsToFetch:PFObject?
override func viewDidLoad(){
super.viewDidLoad()
yourObjectWhichIsToFetch.fetchInBackgroundWithBlock({
(object, error) -> Void in
if error == nil {
//update the UI
}
})
}
}
With this code, you don't need to show any loading note (what is really ugly).

Related

Segue is not working, and i can't figure out why

I have an if...then statement in the ViewDidLoad method for the view that acts as my storyboard entry point.
Basically, I am doing a check to see if there is any data in core data, to indicate that they've completed a small "setup form".
If it is found that the core data is empty or that the app has not been properly set up, I want it to automatically kick them over to the settings view with a segue.
My ViewDidLoad method looks like this:
override func viewDidLoad() {
super.viewDidLoad()
//Get any entries from the App Settings Entity
getAppSettings()
//If any entries are found, check to see if the setup has been completed
if (appSettings.count > 0) {
print("We found entries in the database for App Settings")
if (appSettings[0].setupComplete == false) {
print("Setup has not been completed")
self.performSegue(withIdentifier: "toAppSettings", sender: self)
} else {
print("Setup is completed")
//Load the settings into global variables
preferredRegion = appSettings[0].region!
usersName = appSettings[0].usersName!
}
} else {
print("We found no entries in the database for App Settings")
self.performSegue(withIdentifier: "toAppSettings", sender: self)
}
}
I made sure that the segue does exist, and that the identifier for the segue is exactly as I have it in the quotes (I even copied & pasted all instances of it to make sure that they are all consistent).
I also went the extra mile and put a checker in the "prepare for segue" method, to print whether it was getting called, and who the sender was:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("We're getting ready to segue!")
print(segue.identifier)
}
Both of those items get printed to the log, which tells me that the segue is being recognized and that the app is attempting to fire it. But - for some reason that I can't figure out - it simply isn't firing.
Any ideas what I am missing here?
I have an if...then statement in the ViewDidLoad
But that's the problem. viewDidLoad is way too early for this. Remember, all viewDidLoad means is that your view controller has a view. That's all it means. That view is not yet in the interface, and the view controller itself may not even be in the view hierarchy! It's just sitting out there in object space. You cannot segue from here; there is nothing to segue from.
Try waiting until viewDidAppear. If that makes it work, you might try moving it back to viewWillAppear, but I don't guarantee anything. Keep in mind that these methods can be called multiple times, so you might also need a flag to make sure that this segue fires just the once.

IOS - I want to recycle the server data on Viewcontroller

When we move the a segue from A view to B view or from b view to A view, viewdidload get data from server all the time
So, can we keep the data that viewdidload get at first excute, without starting viewdidload each page?
It's waste of time to get data all the time, when we open each page.
From now we using pageviewcontroller, I think it is inappropriate it.
I using swift language.
If you have good idea, please let me know.
There are very many tutorials on the internet that show how to do what you want. Try a google search on swift pass data between view controllers.
At its very simplest, the second controller needs to have one or properties that can hold data from the first controller. The first controller must implement the following function:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
let secondVC = segue.destinationViewController as! ViewControllerClass
// Pass data to the second view controller.
secondVC.dataFromServer = dataFromServer
secondVC.otherData = otherData // etc.
}
The data will then be passed from the first controller to the second.

Unable to call embedded segue the second time

I'm trying to build an app similar to Instagram, and I'm stuck at the comments portion. On the left side of the image, it is a VC that has an embedded container view with UITextField and UIButton at the bottom. The container view is embedded with a UITableView that contains all the user profile image, username and the comment itself.
At first load, it can perfectly grab all comments for that post from server side, and displayed perfectly. However, I am unable to call the segue again using prepareForSegue to update the UITableView. I'm receiving an error:
There are unexpected subviews in the container view. Perhaps the embed
segue has already fired once or a subview was added programmatically?
Below are my codes:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "getCommentSegue"){
if let destination = segue.destinationViewController as? CommentsTVC{
if(!self.commentID.isEmpty){
destination.UpdateCommentRow(self.profileImage, commentID: self.commentID, comment: self.postComment, dateTimePost: self.dateTime)
self.commentID = String()
}
destination.postID = self.postID
}
}
}
And after successfully adding a row to my database in the dispatch_async:
self.performSegueWithIdentifier("getCommentSegue", sender: nil)
I've also noticed that when it append new comment to my existing object that stores all the comments, the count for it is 0. I believe it is taking a new reference for the object. Please help!
embed navigationcontroller to container view and then try. It may solve youar problem i think..!!
Remove your container view's subviews before you call performSegue.

How to keep user inputs within corresponding text fields after segue [Swift]

I have two view controllers, first view containing "user form" for inputs and second to display the final results. Everything seems to be working fine, i.e. I can send the final results using "prepareForSegue" function (see below)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var SecondVC: SecondViewController = segue.destinationViewController as! SecondViewController
SecondVC.receivedDP_Summary = summaryDP
SecondVC.receivedDC_Summary = summaryDC
SecondVC.receivedDP_CA_Summary = summaryDrillPipe_CsgAnnulus
SecondVC.receivedDC_CA_Summary = summaryDrillCollar_CsgAnnulus
}
However, as soon as I return to first control view after initialising segue, all the user inputs disappear. Is there any way to store the user inputs within the respective text field so they can be manipulated to see varying results?
I am still very new to programming, so I will really appreciate any help

if statement for buttons in swift

I am coding a program which its home has 6 buttons
if you press a button, it shows a TableView when a row is pressed, it shows new viewconroller which show Row Data Details
the TableView takes its data from JSON URL and this JSON URL has all data on it (6 section).
button(X) to show Section(X)Data
[X=1; X=<6]
i coded it with a long way: every button(X) leads to [Button(X)ViewContoller] and every has [Button(X)TableViewCell]
[X=1; X=<6]
so i have 6 ViewContoller and 6 TableViewCell file.
i think about make an If statement for the 6 buttons instead of separated 2 file for every button, so that what i mean:
if button(X) is pressed,it will show Section(X)Data in the TableView
[[X=1; X=<6]]
i tried to do it a lot, but no way
can any one help me on If statement coding?
You just have to:
Set different tags for the buttons
"Plug" all the buttons in the same method
Check which button was clicked and change set your model accordingly
Tip: You can access properties of your destination view controller using the segue.destinationViewController property inside the prepareForSegue(segue: sender:) method.
EDIT: For example:
Create var buttonTag : Int?
Create a method like #IBAction func clicked(sender: UIButton) {
self.buttonTag = sender.tag
}
Pass it on the way you think is betteroverride func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
segue.destinationViewController?.buttonTag = self.buttonTag
}
Do whatever you have to do with data in your destination view controller

Resources