Snippets

Ronald Oussoren Crude hack for using a geocoded from async Python code

Created by Ronald Oussoren
import objc
import Foundation
import CoreLocation


# --- Crude asyncio emulation ---

class Future:
    def result(self):
        return self._result

    def set_result(self, value):
        self._result = value
        if hasattr(self, '_done_callback'):
            self._done_callback(self)

    def add_done_callback(self, callback):
        self._done_callback = callback
        if hasattr(self, '_result'):
            self._done_callback(self)

    def __await__(self):
        if not hasattr(self, "_result"):
            yield self

        return self.result()

    __iter__ = __await__

def schedule(task, value=None):
    def done_callback(future):
        schedule(task, future.result())

    try:
        v = task.send(value)
    except StopIteration:
        print(f"Task {task} done")
        return

    if isinstance(v, Future):
        v.add_done_callback(done_callback)


# ---- Category on CLGeocoder

def geocodeAdressString_(self, address):
    fut = Future()

    def handler(placemarks, error):
        print("have result")
        fut.set_result((placemarks, error))

    self.geocodeAddressString_completionHandler_(address, handler)
    return fut

CoreLocation.CLGeocoder.geocodeAdressString_ = objc.python_method(geocodeAdressString_)

# --- The actual code


async def main():
    print("Before")
    coder = CoreLocation.CLGeocoder.alloc().init()
    placemarks, error = await coder.geocodeAdressString_("1600 Pennsylvania Ave NW, Washington, DC 20500, USA")
    print(f"placemarks: {placemarks}")
    print(f"error: {error}")


# --- Stuff to ensure there's a working runloop

schedule(main())

loop = Foundation.NSRunLoop.currentRunLoop()
loop.runUntilDate_(Foundation.NSDate.dateWithTimeIntervalSinceNow_(3.0))

Comments (0)