omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    objc_util wishlist

    Pythonista
    3
    8
    5967
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • scj643
      scj643 last edited by scj643

      I have found myself using objc_util a whole lot. Heck my pride and joy of a library is made with it

      Some things I wish objc_util had are

      Better ways of responding to blocks.

      A block should have it's own accessible class that functions within the block can access. Also a block should be self contained and not having to push to a global variable

      class Block(object):
          def __init__(self):
              self.someValue = 1
          def callOnFinish(self, passed_value):
              self.someValue = passed_value
      

      Better type error handling

      Currently objc_utils throws very cryptic errors when a type issue happens with an objc function. The type expected should be stated in the error

      Error objects

      If something has an option that is an NSError a built in part of objc_util should provide that. (I currently have an implementation but it's strange)

      Though in all I'm still really happy with objc_util

      1 Reply Last reply Reply Quote 0
      • lukaskollmer
        lukaskollmer last edited by

        @scj643 said:

        Currently objc_utils throws very cryptic errors when a type issue happens with an objc function

        What exactly do you mean? I never found the objc_util errors to be cryptic at all.

        1 Reply Last reply Reply Quote 0
        • scj643
          scj643 last edited by

          It doesn't tell you what type it expected

          1 Reply Last reply Reply Quote 0
          • lukaskollmer
            lukaskollmer last edited by

            @scj643 because it doesn't know. The objc runtime can only get the expected type encoding of an argument or a method's return value. The type encoding specifies which primitive type an argument should be (float/int/char/etc) or whether it is an object. But since ObjC classes are basically just glorified structs, the runtime can't differentiate between different classes. (That's why objc has the id type to represent "any objc-object")

            NSHipster on Type Encodings

            1 Reply Last reply Reply Quote 0
            • scj643
              scj643 last edited by

              It doesn't actually say what type it wants
              example

              v = UIView.new()
              v.setAlpha_('t')
              
              1 Reply Last reply Reply Quote 0
              • lukaskollmer
                lukaskollmer last edited by

                @scj643 it says that the type error is caused by the 3rd argument (which makes sense since 1 is self and 2 is cmd).
                And it can't say which type it wants because it doesn't know what to expect, it just knows that what it got was wrong

                1 Reply Last reply Reply Quote 0
                • JonB
                  JonB last edited by

                  Actually, since objc_util is setting up the ctypes call (based on the method encoding), it does know the types that are needed. For instance, you can copy objc_util and make the following changes (two places, in ObjCClassMethod and ObjCinstanceMethod) where the objc_msgSend calls are:

                  			try:
                  				res = objc_msgSend(obj.ptr, sel(self.sel_name), *args)
                  			except ctypes.ArgumentError as e:
                  				argnum=int(re.match('argument (\d*):',e.args[0]).groups()[0]) #1based
                  				e.args=('{} UserArgument #{}: Expected:{}, Got {}'.format(self.sel_name,argnum-2,argtypes[argnum-3], type(args[argnum-3])), )
                  				raise
                  

                  which produces a traceback like

                  >>> v = UIView.new()
                  >>> v.setAlpha_('t')
                  Traceback (most recent call last):
                    File "<string>", line 1, in <module>
                    File "/private/var/mobile/Containers/Shared/AppGroup/C534C622-2FDA-41F7-AE91-E3AAFE5FFC6B/Pythonista3/Documents/objc_util3.py", line 901, in __call__
                      res = objc_msgSend(obj.ptr, sel(self.sel_name), *args)
                  ctypes.ArgumentError: setAlpha: UserArgument #1: Expected:<class 'ctypes.c_void_p'>, Got <class 'str'>
                  

                  Frankly, I have never understand why the python ctypes.ArgumentError doesnt already contain that info.

                  1 Reply Last reply Reply Quote 0
                  • JonB
                    JonB last edited by JonB

                    @scj643 re: blocks, you can always add instance variables (functions are objects in python).

                    def myblk(blk, arg):
                        if myblk.x:
                            return myblk.x
                    myblk.x=2
                    ...
                    blk=ObjCBlock(myblk)
                    

                    It would be nice to have a ObjCBlock as decorator:

                    @ObjCBlock(argtypes=[c_void_p], restype=None)
                    def myfun(blk, someargs):
                        ...
                    

                    Also, you can have blocks that live as instance methods:

                    class MyDelegate(object):
                    ...    def myblock(self,_blk):
                    ...       print(self.x)
                    ...    def __init__(self):
                    ...       self.x=10
                    ...    
                    >>> m=MyDelegate()
                    >>> m.blk=ObjCBlock(m.myblock,argtypes=[c_void_p]
                    

                    This can let you associate other objects with a particular block, to avoid the need for globals.

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post
                    Powered by NodeBB Forums | Contributors