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.


    Dealing with a completion handler

    Pythonista
    objcutil
    2
    8
    3264
    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.
    • mcriley821
      mcriley821 last edited by mcriley821

      I’m trying to make an notification system that will send a system notification when there’s a new topic on the most recent section of the forum. I’m trying to use the objc_util to schedule the function to the background threads. The function itself works, and sending the update to the background works, but the scheduler doesn’t repeat the function after the interval time. In: https://developer.apple.com/documentation/foundation/nsbackgroundactivityscheduler?language=objc
      , it says that the scheduler won’t repeat if you don’t invoke the completion handler and send it the “all good flag” (integer 1).

      I have no idea how to send this flag to the completion handler. I’ve been through plenty of crashes to no avail lol. Here’s the code:

      
      import requests as r
      from bs4 import BeautifulSoup as soup
      import notification
      from objc_util import *
      
      def update(_cmd,completion_handler):#not sure on number of args or types
      	with open('most_recent.txt','rb') as f:
      		most_recent=f.read()
      
      	print('checking') #debug
      	page=r.get('https://forum.omz-software.com/recent')
      	page=soup(page.content,'html.parser')
      	newest=page.select('meta')[8]
      	content_name=newest.attrs.get('content')
      	if bytes(content_name,'utf8') != most_recent:
      		print(content_name)#debug
      		with open('most_recent.txt','wb') as f: 
      			f.write(bytes(content_name,'utf8'))
      		notification.schedule(message=f'Newest on the Pythonista Forum: {content_name}',action_url='https://forum.omz-software.com/recent',title='Pythonsita Forum')
      	else:#debug
              notification.schedule(message='Nothing new...',title='Pythonista Forum')#debug
          #ObjCInstance(completion_handler).completion=1#doesnt work
      	return
      	
      scheduler=ObjCClass("NSBackgroundActivityScheduler").alloc().initWithIdentifier_('com.omz-software.Pythonista3.update_forums')
      scheduler.setInterval_(10)#more time when working
      scheduler.setTolerance_(5)
      scheduler.setRepeats_(True)
      scheduler.setQualityOfService_(25)#may change when working 
      #not sure on restype or argtypes either 
      block=ObjCBlock(update,restype=None,argtypes=[c_void_p,c_void_p])
      scheduler.scheduleWithBlock_(block)
      
      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp @mcriley821 last edited by

        @mcriley821 did you check _objc_exception.txt file?

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

          @cvp No exception file is created usually. I forgot what I did one time, but I got an exception once, and it said wrong selector sent to instance, during the first repeat. I’ve tried a ton of things though. Returning 1; 1,2,3 args; Different argtypes; different restypes;
          The current code is one of the few that will actually run, and I feel it’s the least convoluted.

          cvp 1 Reply Last reply Reply Quote 0
          • cvp
            cvp @mcriley821 last edited by

            @mcriley821 Is NSBackgroundActivityScheduler not only a MacOS object?

            mcriley821 1 Reply Last reply Reply Quote 0
            • mcriley821
              mcriley821 @cvp last edited by

              @cvp I just read that in the Apple docs, but how could I even create the class if that was true?

              cvp 1 Reply Last reply Reply Quote 0
              • cvp
                cvp @mcriley821 last edited by

                @mcriley821 I don't know, sorry. And strange because your block is called 🤔

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

                  Maybe @JonB has experienced this before?

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

                    Found a better solution @cvp by digging in @JonB objc_hacks.

                    import requests as r
                    from bs4 import BeautifulSoup as soup
                    from objc_util import *
                    import notification
                    import ctypes
                    
                    class _block_descriptor (Structure):
                      _fields_ = [('reserved', c_ulong), ('size', c_ulong), ('copy_helper', c_void_p), ('dispose_helper', c_void_p), ('signature', c_char_p)]
                    InvokeFuncType = ctypes.CFUNCTYPE(None, *[c_void_p, ctypes.c_int])
                    class _block_literal(Structure):
                      _fields_ = [('isa', c_void_p), ('flags', c_int), ('reserved', c_int), ('invoke', InvokeFuncType), ('descriptor', _block_descriptor)]
                     
                    
                    def update_forum(_cmd,_comp):
                    	comp=ObjCInstance(_comp)
                    	blk=_block_literal.from_address(_comp)
                    	blk.invoke(comp,1)
                    	with open('most_recent.txt','rb') as f:
                    		lst=f.readlines()
                    		most_recent,count=lst[0][:-1],lst[1]
                    	url='https://forum.omz-software.com/recent'
                    	page=r.get(url)
                    	page=soup(page.content,'html.parser')
                    	newest=page.select('meta')[8]
                    	content_name=newest.attrs.get('content')
                    	content_name=bytes(content_name,'utf8')
                    	post_count=newest.find_all('span')[2].attrs.get('title')
                    	post_count=bytes(post_count,'utf8')
                    	
                    	if content_name != most_recent or post_count != count:
                    		with open('most_recent.txt','wb') as f: 
                    			f.writelines([content_name,
                    			b'\n',
                    			post_count])
                    		notification.schedule(
                    			message=f'Newest on the Forum: {content_name.decode()}',
                    			action_url=url,
                    			title='Pythonista Forum',
                    			identifier='Forum_Updater'
                    			)
                    	#else:
                    		#notification.schedule(
                    			message='Nothing new...',
                    			title='Pythonista Forum',
                    			identifier='Forum_Updater'
                    			)
                    	return
                    	
                    scheduler=ObjCClass('NSBackgroundActivityScheduler').alloc().initWithIdentifier_('Scheduler')
                    scheduler.setRepeats_(True)
                    scheduler.setInterval_(10*60)
                    scheduler.setTolerance_(60)
                    scheduler.setQualityOfService_(25)
                    
                    block=ObjCBlock(update_forum,restype=None,argtypes=[c_void_p,c_void_p])
                    scheduler.scheduleWithBlock_(block) 
                    

                    Sadly, it only works when in the app. It does free up the console though

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