This question already has answers here:
Why does setState take a closure?
(2 answers)
Closed 4 years ago.
Why Flutter defines that we should call:
setState(() { _counter++});
instead of:
_counter++;
setState(() {});
As far as I can see in setState() code, it doesn't use anything that's passed as a parameter anyway.
The end result in release mode is the same.
But in debug you get an assert for free that checks that the callback inside setState() does not return a Future and it returns immediately.
But if you are sure the callback is synchronous, the result in debug is the same.
Related
I know that these two are the same.
counter++;
setState((){});
setState((){
counter++;
};
but why does it work?
setState((){});
counter++;
I can see the change of counter even I changed it after calling setState function.
You don't actually need to do count++ inside the setState.
If you look at the documentation/code https://api.flutter.dev/flutter/widgets/State/setState.html, you'll see that the only line that matters is _element!.markNeedsBuild();.
setState() will basically rebuild your widget. And since you modified the instance of your widget with count++, the updated count will appear on the screen.
setState takes a callback and it is recommended to apply your state modifications inside it as it provides some useful error messages that will help you when debugging if you are doing something wrong.
This question already has answers here:
Checking if Firebase snapshot is equal to nil in Swift
(2 answers)
How do I check if a firebase database value exists?
(6 answers)
Closed 2 years ago.
Running a Firebase closure such as:
databaseRef.observe(.childAdded) { (snapshot) in
...
}
When first run it will go and get the data and will also execute its closure whenever data is added. This is as it should be. However, when you first fire off this method, and there is no data to get, the closure never returns. In this way there is no way to tell if there is no data or if all of the data just hasn't been gotten yet. Without the closure firing, we cannot look at the snapshot to see if it exists.
Given the documentation indicates that you can interrogate the snapshot to see if it exists or if the values are nil, there must be a way to get called back initially. Again subsequent data added will call back this closure and the closure will come back if there is data there initially.
What am I missing about getting an initial callback if there is no data?
Update:
To provide a working solution which was not provided in the links given indicating this was a duplicate. The reason for the issue - which Frank answered perfectly here and in the thread links he provided - was due to the the way .childAdded works. Frank indicated that one can call both a .value and a .childAdded on the same query and the initial data will not be loaded twice. Based on this key information, I went about handling this in the following way:
databaseRef.observeSingleEvent(.value, with: { (valueSnapshot) in
if !valueSnapshot.exists() {
[do stuff based on the absence of data]
}
databaseRef.observe(.childAdded) { (childSnapshot) in
[do stuff based on children present and when children added]
}
}
The outer event will fire once only. The inner event will be set as a listener so future children added will be executed within its closure only.
A .childAdded event is fired for each child node that exist initially, or that is added later. If there are child nodes, .childAdded is not fired.
If you want to know whether data exists, you should observe the .value event.
If you observe both .child... and .value on the same reference/query, Firebase will only retrieve the data once. So there is no extra data transfer to observe both events.
Also see:
How do I check if a firebase database value exists?
Checking if Firebase snapshot is equal to nil in Swift
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
How can I wait for a function that itself has an async operation to finish?
Let me give you an example:
Function_A fetches a photo from gallery. Fetching operation will be executed asynchronously using fetching closure.
I call Function_A in Function_B and I want to wait the photo fetching operation to finish, and after that continue my code.
What I've tried:
I've used dispatch group but it has not worked. I've also tried to call Function_A in a sync block, and this was unsuccessful too.
How can I wait for this operation to finish? Can be this problem because of running fetching operation into another queue?
Update:
This is what I did:
class imageFetch: NSObject{
var theImage: PHAsset? = nil
func Function_A(){
let fetchOption = PHFetchOptions()
PHPhotoLibrary.requestAuthorization { (authStatus) in
// It seems code will be executed asynchronously from here
if authStatus == .authorized{
let imageAsset = PHAsset.fetchAssets(with: .image, options: fetchOption)
// Select image and save it in theImage
// I know I can send a closure and run it here
}
}
}
}
And in another class I call that function:
class edit: NSObject{
funct Function_B(){
var imageFetchIns = imageFetch()
// I want below code to execute asynchronously
imageFetchIns.Function_A()
// Now I want to wait last operation to finish
}
}
Without code is quite difficult to understand what is going on. If you take a look to Using dispatch groups to wait for multiple web services you will find what is going on.
Otherwise you can start using NSOperation and NSOperationQueue. In fact, if you have two operations, you can add a dependency between them. In other words, you can say that an operation can start only after the one it depends on has finished is execution. In addition to that, an operation has also the benefits to be cancellable. Useful when you want to deal with user actions, for example.
NSOperation and NSOperationQueue Tutorial in Swift will give you a very good intro on how to use them.
What I would like to stress out with operations is that an operation (especially when you subclass it) represents a self-contained task that can be reusable - in your project or in different projects as well.
This question already has answers here:
how to cancel out of operation created with addOperationWithBlock?
(2 answers)
Closed 8 years ago.
So, I am using the addOperationWithBlock^{}method of the NSOperationQueue and I want to put the fine grained isCancelled property check at points in the operation code. How do I get the instance of the operation that will run while in this block?
For example, this is my code snippet:
[operationQueueInstance addOperationWithBlock:^{
if (!???.isCancelled){
NSlog(#"Instruction 1");
}
if (!???.isCancelled){
NSlog(#"Instruction 2");
}
NSlog(#"Instruction 3");
}];
How do I get the instance of the operation this block would run in so that I can evaluate the isCancelled property for the instructions?
TIA
From the Apple docs:
You should not attempt to get a reference to the newly created
operation object or divine its type information.
You could instantiate a NSBlockOperation and assign it to a variable to keep an explicit reference instead.
addOperationWithBlock seems to be a shortcut for whenever you don't need a reference to the operation object.
Make sure to mark your block operation with the __block storage qualifier to avoid retain cycles.
This question already has answers here:
Check whether or not the current thread is the main thread
(13 answers)
Closed 9 years ago.
My code needs to guarantee a certain operation run on the main thread, but calls may come from background threads.
To detect situations in the background I was using the following:
- (void)selectorToRunInMainThread:(id)arguments
{
// push to main thread
if ([NSRunLoop currentRunLoop] != [NSRunLoop mainRunLoop])
{
[self performSelectorOnMainThread:#selector(selectorToRunInMainThread:) withObject:arguments waitUntilDone:NO];
return;
}
/*
... function content ...
*/
}
This works on iOS 4 and iOS 3.2 but not on iOS 3.1.3 and earlier. In these earlier versions, the function will keep getting called in an endless loop.
Changing the comparison to:
if (![[NSRunLoop currentRunLoop] isEqualTo:[NSRunLoop mainRunLoop]])
has no effect, they still never compare to the same value.
I found a solution that appears to be working, but I'd like to see what other people suggest first.
[NSThread isMainThread] and, if not, dispatch via any of a number of mechanisms to the main thread (what you have is fine).