I've created simple application using Page-Based Application template. All data stored inside var pageData = NSArray() and in the Apple's example it initialized inside init method of ModelController class. And now I need to update pages with the data received from the server. I made method updateDataFromServer inside ModelController class where put json request to server and updating pageData. If I tried to call my updateDataFromServer from the init of ModelController everything going wrong. From which place I should call updateDataFromServer and how to update pageData correctly? Maybe func updateDataFromServer should be placed in other place?
Source code: http://github.com/stillfinder/UAH-Rate
You can put your mathod inside the RootViewController which may subclass of UIViewController, you can put your method in that class, and call it from viewDidAppear.
As soon your method get response from the server, you can reload data source in rootview itself, and copy that array to the modelViewController so the PaginationViewController - datasource get update.
You can post your code for more help.
May this helps you.
HTH, Enjoy Coding!!
Related
I have two view controllers that I am working on which both inherits from a Base view controller
class A_ViewController: BaseViewController
class B_ViewController: BaseViewController
Both of those VC interacts heavily with my firebase database. So I want a variable to keep track of all the downloaded items so those two VC can access it without the need to re-download the file again.
I tried to put a variable name in BaseViewController for the two A,B class to access
var allPostsDownloaded: [Post]!
So before A_VC downloads any data, it checks for this allPostsDownloaded variable and loads from it if the data exists. If it doesnt exist, I append to this variable. So when switching to B_VC, the same can be done and no data is re-downloaded when not required.
Reason I am not using segue or protocal to pass data around is that the two VC interacts quite heavly with my database. So it was alot cleaner to try and have a mutural data varaible to keep track of where things are.
However, the problem is that i
var allPostsDownloaded: [Post]!
gets called whenever I switch between A and B VC (Which are tabs). This will cause the variable to be empty and de-initialised.
I guess I could use a global variable instead but that is not good practice? Could anyone please explain why it gets re-called when new tab shows up? And the best solution for this.
as #avi mentioned create new singleton class, then you can pass and read easily. Below is an example
class PersistentData
{
static let sharedInstance = PersistentData()
// your global persistent variable
var allPostsDownloaded = [Post]()
}
So in your controllers you can simple read and set as below
// read
print(PersistentData.sharedInstance.allPostsDownloaded)
// set new data. this just example, hence depends on your case
PersistentData.sharedInstance.allPostsDownloaded.append(newPost)
PersistentData.sharedInstance.allPostsDownloaded = posts
also keep in mind that if you want to read new value when switching between tabs, you can get the updated in viewDidAppear or viewWillAppear
You can create a Singleton class with a instance variable and can save all downloaded data, and can access singleton class variable from any where of your project's classes.
Try this with a plain new Single View application template, so in the storyboard there is only 1 view controller
In the ViewController
class ViewController: UIViewController {
override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
print(self)
return self
}
}
We can see that it is printed 3 times, why is that?
In the spec
Overridden by subclasses to substitute another object in place of the object that was decoded and subsequently received this message.
You can use this method to eliminate redundant objects created by the coder. For example, if after decoding an object you discover that an equivalent object already exists, you can return the existing object. If a replacement is returned, your overriding method is responsible for releasing the receiver.
This method is invoked by NSCoder. NSObject’s implementation simply returns self.
Why is it called many times?
I have tested with your suggest and I see that it call 2 times. And with this I describe my knowledge below:
ViewController will call initWithCoder and after that will call awakeAfterUsingCoder
Continue ViewController will call loadNibNamed, loadNibNamed still call awakeAfterUsingCoder again.
This infomation I have referenced from other source. You can view and if have some info. Please share with me. I am very appreciate :)
From StackOverflow
Cocoanuts
fantageek.com
I was using this code to pass data between controllers.
InterfaceController.reloadRootControllersWithNames(["1","2","3"], contexts: ["adf","asd","asd"])
I called this code in willActivate() method, that you can see here.
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
InterfaceController.reloadRootControllersWithNames(["1","2","3"], contexts: ["adf","asd","asd"])
}
I have no idea about whats wrong with this code, in apple watch, the app is just refreshing again and again. Is there any other method to pass data between interface controllers while we use page based navigation.??
Please Find the below way of passing data in paged-based navigation in watch application (Watch os 2 and later).
Note :
An array of strings, each of which contains the name of an interface controller you want to display in the page-based interface. In your storyboard, the name of an interface controller is stored in the object’s Identifier property, which is located in the attributes inspector. The order of the strings in the array is used to set the order of the corresponding interface controllers. This parameter must not be nil or an empty array.
Objectiv C
[self presentControllerWithNames:#[#"FirstViewController",#"SecondViewController",#"ThirdViewController"] contexts:#[#"adf",#"asd",#"asd"]];
Swift
let controller = ["FirstViewController","SecondViewController","ThirdViewController"]
let pageContexts:[AnyObject]? = ["adf","asd","asd"]
presentControllerWithNames(controller, contexts: pageContexts)
If you call reloadRootControllersWithNames(NSArray, contexts: NSArray) onto the view controller, it will do as the function is titled: reload. Therefore, you have a view controller that refreshes all 3 of the items in the first Array you give, and then, since your current view controller calls willActivate() upon loading, it infinitely refreshes.
I don't have enough reputation to make this a comment, but my suggestion here is to find a method that you can call on an instance of the watch interface you want to in order to pass data.
What I mean is, if you have each interface as its own class, then you can make a method in the interface you want to get to that sets a property to whatever data you want to transfer before you present the interface.
I also use Objective-C more than Swift, but here's what my guess is as to what the Obj-C code would come to:
SecondWatchInterface *secondWatchInterface = [SecondWatchInterface new];
[SecondWatchInterface setSomeDataWithAStringValue:#"Foo"];
[self presentWatchInterface:SecondWatchInterface]
In Swift, I'm thinking this would equate to:
SecondWatchInterface *secondWatchInterface = SecondWatchInterface.new()
secondWatchInterface.setSomeDataWithAStringFile:"Foo"
presentWatchInterface(secondWatchInterface)
I'm unfamiliar with WatchKit myself; I typically use SpriteKit. I hope I helped identify what the problem was, at least!
To pass data between interface controllers you need to go for this method:
presentControllerWithName(“Second Watch Controller”, context: [“segue”:“pagebased”,“data”: "Data Passed Successfully”]);
Also, you can refer to this example: http://www.informit.com/articles/article.aspx?p=2272657&seqNum=3
I'm dealing with a design Problem right now. I'm writing a Swift App, wich has a Storyboard with multiple ViewControllers and a Class HTTPRequests, wich performs GET and POST Requests on a RESTful Webservice.
My Problem right now is as following. From a view controller, I have to perform a a GET Request on the Webservice to fetch data. The received Data should be displayed trough this view controller on the specific view.
I see two possibilities to achieve this right now:
Put the Request function into the ViewController. Perform an asynchronus request and update the view in this asynchronus task as soon as data are received.
I don't really like this approach for two reasons. First, I don't want the Request function inside the ViewController, because I need the same function in multiple ViewControllers and this leads to code duplication. Second, I don't want to update the view inside the asynchronus task.
Put the Request function into the HTTPRequests (Singleton) Class. Call the requests from a ViewController and get a return value back. With this value, the ViewController is able to update its view.
I like this approach, because it's in design concerns "cleaner". My only problem is the return value. How can I return a value from an asynchronus task in Swift?
If possible please with code examples.
Or is there a better approach than those two?
Edit:
Thanks to your answers and this Blog Post I could successfully implement approach 2 with delegates.
You don't have to use a singleton, but rather you can have a separate class (model) that does all the web requests. You can implement a protocol in the model and set you view controller to be delegates. Sorry I'm on mobile so I can't include code, but I'd be glad to add it later.
I have a DataController for my ViewController, which handles loading data from the internet. I set the DataController as the data source for my ViewController, and it works fine. But now I want to display a progress bar as the data loads, so I was thinking of having the ViewController be a delegate of the DataController, and be notified of when loading starts, continues, and ends. Obviously, this recursive delegation leads to a Bad Access while the stack is still showing me assembly. How should I implement this situation?
I've never used this exact dataController pattern you're mentioning, but my common implementation for something along these lines is:
Declare a NSArray or NSMutableArray as a member your UIViewController subclass
Create a class that using ASIHTTP or NSURL to load data from the web, and set that class as the delegate for the ASIHTTP or NSURL
Create a protocol in that data access class that your UIViewController adheres to
Create an instance of that class in your UIViewController, and start the fetching process (asynch)
When the requests complete (or are giving progress notice) to your data access class, send that information via delegate to your UIViewController
When the request fully completes return the list of items to a delegate method and store that data locally in the array from step 1.
There are various ways to do this depending on your circumstances, but I just wanted to give you an idea.
Never mind; turns out the issue was due to a premature release. I'm dealing with objects that should never be dealloced (data source and root view controller) and I set up the delegation after both are created, so there's really no issue here.