Waiting for mouse input in a while loop (OS X)

Hello,

I have a very simple while loop and I want to wait for a mouse click(can be
a different input, not important) between every step. What I want to
achieve is something like this:

while (i < 50){
    print(i)
    i += 1
    waitForMouseClick() //Wait here for user input.}

I also use Sprite Kit if you can think a solution related to it.

Cheers,

Ergin

Hi Ergin,
Are you familiar with how events are delivered via the application runloop? Essentially, you should not create a top-level loop that waits for input; the application runloop does this for you. If you want to accumulate 50 clicks, create the counter variable in the appropriate NSResponder (or UIResponder on iOS), e.g. your root NSView or your NSViewController. Then override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

···

On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users <swift-users@swift.org> wrote:

Hello,

I have a very simple while loop and I want to wait for a mouse click(can be a different input, not important) between every step. What I want to achieve is something like this:

while (i < 50){

print(i)

    i
+= 1

    waitForMouseClick
() //Wait here for user input.
}
I also use Sprite Kit if you can think a solution related to it.

Cheers,

Ergin

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Thank you for help. Maybe I have over simplified my problem. In my first
example, your advice was totally fine. But when I want to do something more
complex, I could not figure out how to use it. For example, I want to print
each step in my insertion sort. Like this:

for i in 1..<toSort.count{
    var j: Int = i
    while ((j > 0) && (toSort[j-1] > toSort[j])){
        let temp: Int = toSort[j]
        toSort[j] = toSort[j-1]
        toSort[j-1] = temp
        j--
        print(toSort)
        //Wait here.
    }
}

I am looking for a solution without tearing the sorting algorithm into
pieces. (If it is possible.)

Ergin

···

On 23 March 2016 at 18:52, George King <gwk.lists@gmail.com> wrote:

Hi Ergin,
Are you familiar with how events are delivered via the application
runloop? Essentially, you should not create a top-level loop that waits for
input; the application runloop does this for you. If you want to accumulate
50 clicks, create the counter variable in the appropriate NSResponder (or
UIResponder on iOS), e.g. your root NSView or your NSViewController. Then
override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

>
> On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users < > swift-users@swift.org> wrote:
>
> Hello,
>
> I have a very simple while loop and I want to wait for a mouse click(can
be a different input, not important) between every step. What I want to
achieve is something like this:
>
> while (i < 50){
>
>
> print(i)
>
> i
> += 1
>
> waitForMouseClick
> () //Wait here for user input.
> }
> I also use Sprite Kit if you can think a solution related to it.
>
> Cheers,
>
> Ergin
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

I don't know of an easy way to block the main thread and wait for GUI input, without disrupting Cocoa. If you do not need the GUI, then I suggest using the debugger to set a breakpoint; in general it's worth the effort to learn to use the debugger, rather than just print statements. Alternatively, you could read a line from stdin, and then step through your algorithm by hitting return in the terminal. If you are trying to visualize your algorithm it gets trickier to do so without restructuring it to operate within the runloop.

···

On Mar 23, 2016, at 1:48 PM, Ergin Bilgin <erginbil@gmail.com> wrote:

Thank you for help. Maybe I have over simplified my problem. In my first example, your advice was totally fine. But when I want to do something more complex, I could not figure out how to use it. For example, I want to print each step in my insertion sort. Like this:

for i in 1..<toSort.count{
    var j: Int = i
    while ((j > 0) && (toSort[j-1] > toSort[j])){
        let temp: Int = toSort[j]
        toSort[j] = toSort[j-1]
        toSort[j-1] = temp
        j--
        print(toSort)
        //Wait here.
    }
}

I am looking for a solution without tearing the sorting algorithm into pieces. (If it is possible.)

Ergin

On 23 March 2016 at 18:52, George King <gwk.lists@gmail.com <mailto:gwk.lists@gmail.com>> wrote:
Hi Ergin,
Are you familiar with how events are delivered via the application runloop? Essentially, you should not create a top-level loop that waits for input; the application runloop does this for you. If you want to accumulate 50 clicks, create the counter variable in the appropriate NSResponder (or UIResponder on iOS), e.g. your root NSView or your NSViewController. Then override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

>
> On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>
> Hello,
>
> I have a very simple while loop and I want to wait for a mouse click(can be a different input, not important) between every step. What I want to achieve is something like this:
>
> while (i < 50){
>
>
> print(i)
>
> i
> += 1
>
> waitForMouseClick
> () //Wait here for user input.
> }
> I also use Sprite Kit if you can think a solution related to it.
>
> Cheers,
>
> Ergin
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org <mailto:swift-users@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users

Here is an outline on how you might achieve that.

1- Create a background GCD queue and a GCD semaphore.
2- dispatch_async your sort routine on that queue
3- add a call to dispatch_semaphore_wait before starting your sort. This will grab the semaphore.
4- at the //wait here point, call dispatch_semaphore_wait on your semaphore. Since the semaphore was already grabbed, this will block.
5- separately implement some button on your interface, and on the main thread, its action will be to call dispatch_semaphore_signal. This will release the semaphore, and make your sort continue

I haven’t tested it, and there may be some devil in the details, but I think this can work.

Jean-Denis

···

On 23 Mar 2016, at 18:48, Ergin Bilgin via swift-users <swift-users@swift.org> wrote:

Thank you for help. Maybe I have over simplified my problem. In my first example, your advice was totally fine. But when I want to do something more complex, I could not figure out how to use it. For example, I want to print each step in my insertion sort. Like this:

for i in 1..<toSort.count{
    var j: Int = i
    while ((j > 0) && (toSort[j-1] > toSort[j])){
        let temp: Int = toSort[j]
        toSort[j] = toSort[j-1]
        toSort[j-1] = temp
        j--
        print(toSort)
        //Wait here.
    }
}

I am looking for a solution without tearing the sorting algorithm into pieces. (If it is possible.)

Ergin

On 23 March 2016 at 18:52, George King <gwk.lists@gmail.com <mailto:gwk.lists@gmail.com>> wrote:
Hi Ergin,
Are you familiar with how events are delivered via the application runloop? Essentially, you should not create a top-level loop that waits for input; the application runloop does this for you. If you want to accumulate 50 clicks, create the counter variable in the appropriate NSResponder (or UIResponder on iOS), e.g. your root NSView or your NSViewController. Then override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

>
> On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>
> Hello,
>
> I have a very simple while loop and I want to wait for a mouse click(can be a different input, not important) between every step. What I want to achieve is something like this:
>
> while (i < 50){
>
>
> print(i)
>
> i
> += 1
>
> waitForMouseClick
> () //Wait here for user input.
> }
> I also use Sprite Kit if you can think a solution related to it.
>
> Cheers,
>
> Ergin
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org <mailto:swift-users@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

"print(toSort)" is only a placeholder there. Yes, it will be a
visualization. I am thinking of saving each state of "toSort" to another
array and show a fake visualization after sorting is finished. Using stdin
also might be a good solution but not very presentable.

Ergin

···

On 23 March 2016 at 19:55, George King <gwk.lists@gmail.com> wrote:

I don't know of an easy way to block the main thread and wait for GUI
input, without disrupting Cocoa. If you do not need the GUI, then I suggest
using the debugger to set a breakpoint; in general it's worth the effort to
learn to use the debugger, rather than just print statements.
Alternatively, you could read a line from stdin, and then step through your
algorithm by hitting return in the terminal. If you are trying to visualize
your algorithm it gets trickier to do so without restructuring it to
operate within the runloop.

On Mar 23, 2016, at 1:48 PM, Ergin Bilgin <erginbil@gmail.com> wrote:

Thank you for help. Maybe I have over simplified my problem. In my first
example, your advice was totally fine. But when I want to do something more
complex, I could not figure out how to use it. For example, I want to print
each step in my insertion sort. Like this:

for i in 1..<toSort.count{
    var j: Int = i
    while ((j > 0) && (toSort[j-1] > toSort[j])){
        let temp: Int = toSort[j]
        toSort[j] = toSort[j-1]
        toSort[j-1] = temp
        j--
        print(toSort)
        //Wait here.
    }
}

I am looking for a solution without tearing the sorting algorithm into
pieces. (If it is possible.)

Ergin

On 23 March 2016 at 18:52, George King <gwk.lists@gmail.com> wrote:

Hi Ergin,
Are you familiar with how events are delivered via the application
runloop? Essentially, you should not create a top-level loop that waits for
input; the application runloop does this for you. If you want to accumulate
50 clicks, create the counter variable in the appropriate NSResponder (or
UIResponder on iOS), e.g. your root NSView or your NSViewController. Then
override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

>
> On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users < >> swift-users@swift.org> wrote:
>
> Hello,
>
> I have a very simple while loop and I want to wait for a mouse
click(can be a different input, not important) between every step. What I
want to achieve is something like this:
>
> while (i < 50){
>
>
> print(i)
>
> i
> += 1
>
> waitForMouseClick
> () //Wait here for user input.
> }
> I also use Sprite Kit if you can think a solution related to it.
>
> Cheers,
>
> Ergin
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

Thank you. I knew it should be possible with GCD, but I was just not
familiar with semaphores. Now everything perfectly works in the way I want.

Ergin

···

On 23 March 2016 at 20:11, Jean-Denis Muys <jdmuys@gmail.com> wrote:

Here is an outline on how you might achieve that.

1- Create a background GCD queue and a GCD semaphore.
2- dispatch_async your sort routine on that queue
3- add a call to dispatch_semaphore_wait before starting your sort. This
will grab the semaphore.
4- at the //wait here point, call dispatch_semaphore_wait on your
semaphore. Since the semaphore was already grabbed, this will block.
5- separately implement some button on your interface, and on the main
thread, its action will be to call dispatch_semaphore_signal. This will
release the semaphore, and make your sort continue

I haven’t tested it, and there may be some devil in the details, but I
think this can work.

Jean-Denis

On 23 Mar 2016, at 18:48, Ergin Bilgin via swift-users < > swift-users@swift.org> wrote:

Thank you for help. Maybe I have over simplified my problem. In my first
example, your advice was totally fine. But when I want to do something more
complex, I could not figure out how to use it. For example, I want to print
each step in my insertion sort. Like this:

for i in 1..<toSort.count{
    var j: Int = i
    while ((j > 0) && (toSort[j-1] > toSort[j])){
        let temp: Int = toSort[j]
        toSort[j] = toSort[j-1]
        toSort[j-1] = temp
        j--
        print(toSort)
        //Wait here.
    }
}

I am looking for a solution without tearing the sorting algorithm into
pieces. (If it is possible.)

Ergin

On 23 March 2016 at 18:52, George King <gwk.lists@gmail.com> wrote:

Hi Ergin,
Are you familiar with how events are delivered via the application
runloop? Essentially, you should not create a top-level loop that waits for
input; the application runloop does this for you. If you want to accumulate
50 clicks, create the counter variable in the appropriate NSResponder (or
UIResponder on iOS), e.g. your root NSView or your NSViewController. Then
override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

>
> On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users < >> swift-users@swift.org> wrote:
>
> Hello,
>
> I have a very simple while loop and I want to wait for a mouse
click(can be a different input, not important) between every step. What I
want to achieve is something like this:
>
> while (i < 50){
>
>
> print(i)
>
> i
> += 1
>
> waitForMouseClick
> () //Wait here for user input.
> }
> I also use Sprite Kit if you can think a solution related to it.
>
> Cheers,
>
> Ergin
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Make the loop into a function.
call the function everytime a mouseevent happened with appropriate input
counters.

var i = 1
var innerloopCounter = 1
var innerloopRunning = false
// this is the os mouseevent handler
func mouseevent(event:Event) {
if i < toSort.count {
sort(toSort)
}
}
// ++, -- operators will be dropped from swift 3.0
// now these operators are deprecated.
func sort(toSort:[Element]) {
var j = innerloopCounter > 0 ? innerloopCounter : i
if(toSort[j-1] > toSort[j]) {
    let temp: Int = toSort[j]
    toSort[j] = toSort[j-1]
    toSort[j-1] = temp
    innerloopCounter = j - 1
    print(toSort)
  }
  if innerloopCounter == 0 {
i += 1
}
}

···

On Wed, Mar 23, 2016 at 11:36 PM, Ergin Bilgin via swift-users < swift-users@swift.org> wrote:

"print(toSort)" is only a placeholder there. Yes, it will be a
visualization. I am thinking of saving each state of "toSort" to another
array and show a fake visualization after sorting is finished. Using stdin
also might be a good solution but not very presentable.

Ergin

On 23 March 2016 at 19:55, George King <gwk.lists@gmail.com> wrote:

I don't know of an easy way to block the main thread and wait for GUI
input, without disrupting Cocoa. If you do not need the GUI, then I suggest
using the debugger to set a breakpoint; in general it's worth the effort to
learn to use the debugger, rather than just print statements.
Alternatively, you could read a line from stdin, and then step through your
algorithm by hitting return in the terminal. If you are trying to visualize
your algorithm it gets trickier to do so without restructuring it to
operate within the runloop.

On Mar 23, 2016, at 1:48 PM, Ergin Bilgin <erginbil@gmail.com> wrote:

Thank you for help. Maybe I have over simplified my problem. In my first
example, your advice was totally fine. But when I want to do something more
complex, I could not figure out how to use it. For example, I want to print
each step in my insertion sort. Like this:

for i in 1..<toSort.count{
    var j: Int = i
    while ((j > 0) && (toSort[j-1] > toSort[j])){
        let temp: Int = toSort[j]
        toSort[j] = toSort[j-1]
        toSort[j-1] = temp
        j--
        print(toSort)
        //Wait here.
    }
}

I am looking for a solution without tearing the sorting algorithm into
pieces. (If it is possible.)

Ergin

On 23 March 2016 at 18:52, George King <gwk.lists@gmail.com> wrote:

Hi Ergin,
Are you familiar with how events are delivered via the application
runloop? Essentially, you should not create a top-level loop that waits for
input; the application runloop does this for you. If you want to accumulate
50 clicks, create the counter variable in the appropriate NSResponder (or
UIResponder on iOS), e.g. your root NSView or your NSViewController. Then
override `func mouseDown(event: NSEvent)` and increment the counter there.
Hope that helps,
George

>
> On Mar 23, 2016, at 12:35 PM, Ergin Bilgin via swift-users < >>> swift-users@swift.org> wrote:
>
> Hello,
>
> I have a very simple while loop and I want to wait for a mouse
click(can be a different input, not important) between every step. What I
want to achieve is something like this:
>
> while (i < 50){
>
>
> print(i)
>
> i
> += 1
>
> waitForMouseClick
> () //Wait here for user input.
> }
> I also use Sprite Kit if you can think a solution related to it.
>
> Cheers,
>
> Ergin
>
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users