still learning the basics. I have a function in which there is a block, that needs to be repeated without calling the whole function again. How is this done in Swift?
func connected(to peripheral: Peripheral) {
let cwConnection = CWStatusBarNotification()
cwConnection.display(withMessage: "Ring Connected", forDuration: 3)
BluejayManager.shared.getHeliosInfo { (success) in
if success {
// Go on
} else {
// Repeat this block (BluejayManager.shared.getHeliosInfo)
}
}
}
Hey Riyan it's just simple. Here is the solution to your problem. Just put the block in other small method and when you just need to call that block call that small function.
func connected(to peripheral: Peripheral) {
let cwConnection = CWStatusBarNotification()
cwConnection.display(withMessage: "Ring Connected", forDuration: 3)
self.callBluejayManagerShared() // Call of block from method
}
func callBluejayManagerShared(){
BluejayManager.shared.getHeliosInfo { (success) in
if success {
// Go on
} else {
// Repeat this block (BluejayManager.shared.getHeliosInfo)
self.callBluejayManagerShared()
}
}
}
Now when you just want to call block you just need to call self.callBluejayManagerShared() method.
Hope this help you
You can use repeat - while around and BluejayManager.shared.getHeliosInfo check for success as break condition:
repeatGetInfo: repeat {
BluejayManager.shared.getHeliosInfo
{ (success) in
if success
{
// do your stuff.
break repeatGetInfo
} else
{
continue repeatGetInfo
}
}
} while true
Hope this helps
Related
var currentCount = 0
let totalCount = 100
func myEscapingRecursiveFunction(_ json: String, done: #escaping (Bool) -> Void) {
currentCount+=1
if currentCount == totalCount {
done(true)
}
else {
myEscapingRecursiveFunction("xyz") { done in
// what should I do here????
}
}
Calling
// (Initially called here)
myEscapingRecursiveFunction("xyz") { done in
if done {
print("completed") // I want to get response here after the recursion is finished
}
}
I want my function to escape only when the current count is equal to total count, otherwise it should recurse, the problem is that I want to get response in place where it was initially called, but it will always execute the completion handler code where it was last called. here:
You just need to pass the same escaping block to your recurse function.
so call your function like this.
myEscapingRecursiveFunction("xyz", done: done)
I have a KMM app, and there is code:
fun getWeather(callback: (WeatherInfo) -> Unit) {
println("Start loading")
GlobalScope.launch(ApplicationDispatcher) {
while (true) {
val response = httpClient.get<String>(API_URL) {
url.parameters.apply {
set("q", "Moscow")
set("units", "metric")
set("appid", weatherApiKey())
}
println(url.build())
}
val result = Json {
ignoreUnknownKeys = true
}.decodeFromString<WeatherApiResponse>(response).main
callback(result)
// because ApplicationDispatcher on IOS do not support delay
withContext(Dispatchers.Default) { delay(DELAY_TIME) }
}
}
}
And if I replace withContext(Dispatchers.Default) { delay(DELAY_TIME) } with delay(DELAY_TIME) execution is never returned to while cycle and it will have only one iteration.
And ApplicationDispatcher for IOS looks like:
internal actual val ApplicationDispatcher: CoroutineDispatcher = NsQueueDispatcher(dispatch_get_main_queue())
internal class NsQueueDispatcher(
private val dispatchQueue: dispatch_queue_t
) : CoroutineDispatcher() {
override fun dispatch(context: CoroutineContext, block: Runnable) {
dispatch_async(dispatchQueue) {
block.run()
}
}
}
And from delay source code I can guess, that DefaultDelay should be returned and there is should be similar behaviour with/without withContext(Dispatchers.Default)
/** Returns [Delay] implementation of the given context */
internal val CoroutineContext.delay: Delay get() = get(ContinuationInterceptor) as? Delay ?: DefaultDelay
Thanks!
P.S. I got ApplicationDispatcher from ktor-samples.
Probably ApplicationDispatcher is some old stuff, you don't need to use it anymore:
CoroutineScope(Dispatchers.Default).launch {
}
or
MainScope().launch {
}
And don't forget to use -native-mt version of coroutines, more info in this issue
I completed all step of Creative SDK Image component .But,how can i convert this block into Swift language..
id<AdobeImageEditorRender> render = [photoEditor enqueueHighResolutionRenderWithImage:highResImage
completion:^(UIImage *result, NSError *error) {
if (result) {
} else {
}
}];
// Provide a block to receive updates about the status of the render
[render setProgressHandler:^(CGFloat progress) {
print("Do something")
}];
It may not be exactly this, since I don't have the SDK installed, but it should be very close to this:
let render = photoEditor.enqueueHighResolutionRenderWithImage(image) { result, error in
if let result = result {
// do something with result.
} else {
// do something with error.
}
}
render.progressHandler = { progress in
// update progress, if
}
if you reference self in the blocks, you need to put [unowned self] after the brace like this:
render.progressHandler = { [unowned self] progress in
self.updateProgress(progress)
}
So I have a function with a completion block that handles animation and a function calling that function. During the function call the completion block is seemingly skipped over because no print lines are printed. I have tried putting the code to be executed into the main queue but it has not yielded any results. Here is how I'm calling the function:
runAnimations(past.count, currentIteration: 0, animationsArray: past, completion: {
finished in
var randomr = self.randomInRange(0,hi: 3)
println("sell")
past.append(randomr)
for i in past123{
if(past.count >= 10){
}
else{
// have tried with and without dispatch_async.. neither print little did I know
dispatch_async(dispatch_get_main_queue()) {
println("little did I know")
self.incrementGame(past)
}
}
}
})
I know it is not an issue with the past.count if statement because the sell print line is not executed either. A breakpoint at the function call simply shows it skipping over however I am aware this is due to it being in an async thread.
Here is the code for runAnimations function:
func runAnimations(numberToIterate:Int, currentIteration:Int, animationsArray : [Int], completion: ((Bool) -> Void)?) {
UIView.animateWithDuration(1, animations: {
if(animationsArray[currentIteration] == 0){
self.label.text="circle!"
//self.label.alpha = 0.0
}
else if(animationsArray[currentIteration] == 1){
self.label.text="square!"
//self.label.alpha = 0.0
}
else if(animationsArray[currentIteration] == 2){
self.label.text="triangle!"
//self.label.alpha = 0.0
}
else if(animationsArray[currentIteration] == 3){
self.label.text="star!"
//self.label.alpha = 0.0
}
}, completion: {
finished in
println("BRO")
if(currentIteration+1>=numberToIterate){
self.label.alpha = 1.0
println("ook")
}
else{
println("okies")
self.runAnimations(numberToIterate, currentIteration: currentIteration+1, animationsArray: animationsArray, completion: { finished in
})
//self.runAnimations(numberToIterate, currentIteration: currentIteration+1, animationsArray: animationsArray)
}
})
The prints in runAnimation execute properly.
You actually have to call the completion block, which you haven't done by doing
completion(finished)
The completion block you defined can be seen as a separate method, which you need to call. In your case you have left your block as an optional so you must do optional checking as per the standard (completion != nil, etc)
This is a very "swift" guide on a completion block in swift, which is now called a closure. Take a look: here
PubNub offers this snippet in the iOS SDK to call some client methods before the clients gets suspended as a result of the app resigning from active:
- (void)pubnubClient:(PubNub *)client willSuspendWithBlock:(void(^)(void(^)(void(^)(void))))preSuspensionBlock {
if ([client isConnected]) {
preSuspensionBlock(^(void(^completionBlock)(void)){
[client sendMessage:#"Hello my friend" toChannel:[PNChannel channelWithName:#"boom"]
withCompletionBlock:^(PNMessageState state, id data) {
if (state != PNMessageSending) {
NSString *message = #"Message has been sent";
if (state == PNMessageSendingError) {
// Handle message sending error
}
// Always call this block as soon as required amount of tasks completed.
completionBlock();
}
}];
});
}
}
Now XCode is smart enough to convert the crazy blocks syntax in the method declaration to this, which I guess is fine:
public func pubnubClient(client: PubNub!, willSuspendWithBlock preSuspensionBlock: (((((() -> Void)!) -> Void)!) -> Void)!)
I really can't figure out how to port this line though:
preSuspensionBlock(^(void(^completionBlock)(void))
Blocks syntax was always killing me.
The objective-c code is a preSuspension method accepts a block that returns a block that accepts no arguments. Try something like this:
var x: (()-> () -> Void) = { () -> ()->Void in
return {() -> Void in
println("this is returned inner void block")
}
}
preSuspensionBlock(x);
PubNub.sendMessage(chatMessage, googleCloudNotification: nil, toChannel:chatChannel, storeInHistory: true) { (state, obj) -> Void in
if (state != PNMessageState.Sending){
println("Message has been sent")
if(state == PNMessageState.SendingError){
completionHandler(responseStatus: RespStatus.unExpectedServerError)
}
else{
completionHandler(responseStatus: RespStatus.responseSuccess)
}
}
}