Forum Archive

how to return nil in a objc new class function?

ryubai

hey~i need to return none in a objc new class function,but it crash’s when i use return none.how can i solve it? thanks very much.

def tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_(_self,_cmd,_tv,_indexPath):       
        return None
cvp

@ryubai if you try this example, it works.. Thus perhaps do you have another error.

Try to identify the reason of the crash.
Either in _objc_exception.txt in the root or by installing @dgelessus 's code here

ryubai

@cvp thanks

i have checked _objc_exception.txt and saw nothing in this crash.
try the example you provided,when i do a left swipe,it just show “delete” button.
i have no idea how the code below work

    # set actions if swipe
    UIContextualAction = ObjCClass('UIContextualAction').alloc()
    UIContextualAction.setTitle_("Drizzel's action 😅")
    # block does not have parameter nor return, thus we can use a Python def
    UIContextualAction.setHandler_(handler)
    UIContextualAction.setBackgroundColor_(ObjCClass('UIColor').blueColor().colorWithAlphaComponent(0.5))

    UISwipeActionsConfiguration = ObjCClass('UISwipeActionsConfiguration').configurationWithActions_([UIContextualAction])
ryubai

@cvp when i comment # return none,i got it.
thanks very much.

cvp

@ryubai I added this code some time ago to answer to @Drizzel 's question to have a particular action (button) when you swipe but this part of code is not needed.

ryubai

@cvp i try the code below,but still crash,what’s the problem?

from objc_util import *
import ui

@on_main_thread
def main_tableview():
    def tableView_numberOfRowsInSection_(_self, _cmd,_tv,_section):
        return 3

    def numberOfSectionsInTableView_(_self, _cmd,_tv):
        return 1

    def tableView_cellForRowAtIndexPath_(_self, _cmd,_tv,_indexpath):
        cell=ObjCInstance(_tv).dequeueReusableCellWithIdentifier("cell1") 
        if cell==None:
            cell=ObjCClass('UITableViewCell').alloc().initWithStyle_reuseIdentifier_(3,"cell2")

        cell.textLabel().text = 'test'
        return cell.ptr

    def tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_(_self,_cmd,_tv,_indexPath): 
        return None

    tvc1 = create_objc_class('UITableViewController',ObjCClass('UITableViewController'),methods=[tableView_numberOfRowsInSection_,numberOfSectionsInTableView_,tableView_cellForRowAtIndexPath_,tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_])

    return  tvc1.alloc().init().autorelease()   

@on_main_thread
def main():

    root_vc = UIApplication.sharedApplication().keyWindow().rootViewController()
    tbc=main_tableview()
    root_vc.presentViewController_animated_completion_(tbc, True, None)

if __name__=='__main__':
    main()
cvp

@ryubai try

create_objc_class('UITableViewController',ObjCClass('UIViewController'),...

You had defined as superclass the same class UITableViewController.

So, you don't have a crash but the view seems transparent.

You can start with,

    tvc1 = ObjCClass('UITableViewController')

So, you see the TableView but empty as the delegates are not called

JonB

Is returning None valid when working with objc? I can't remember if that gets translated to a null pointer. You may need to return 0, or c_void_p(0)

cvp

@JonB No, no, it was ok with None, as I said in my first reply

ryubai

@cvp i don’t understand how to .. i want to subclass a UITableViewcontroller and add a action when i left swipe a cell.
could you show me the right way in the code i provided?
sorry for my poor understanding.

cvp

@ryubai I'm sorry but I also have some understanding's problem with UITableViewController.
Why don't you want to use a UITableView as subview of an ui.TableView?

cvp

@ryubai this should work with an UITableViewController as you asked

# coding: utf-8
from __future__ import absolute_import
from objc_util import *
import ui
from collections import OrderedDict
from six.moves import range
import console

UITableView = ObjCClass('UITableViewController')
UITableViewCell = ObjCClass('UITableViewCell')

class UITableViewStyle(object):
        UITableViewStylePlain = 0
        UITableViewStyleGrouped = 1

def test_data(number):
    data = OrderedDict()
    valueRange = 7
    for i in range(0,number):
        ii = i * valueRange
        key = str(ii)
        value = []
        for j in range(ii,ii+valueRange):
            value.append(str(j))
        data[key] = value
    return data

data = test_data(1)

def tableView_cellForRowAtIndexPath_(self,cmd,tableView,indexPath):
    ip = ObjCInstance(indexPath)
    cell = ObjCInstance(tableView).dequeueReusableCellWithIdentifier_('mycell')

    if cell == None:
        cell = UITableViewCell.alloc().initWithStyle_reuseIdentifier_(0,'mycell')
    key = list(data.keys())[ip.section()]
    text = ns(data[key][ip.row()])
    cell.textLabel().setText_(text)

    return cell.ptr

def numberOfSectionsInTableView_(self,cmd,tableView):
    return len(data)

def tableView_numberOfRowsInSection_(self,cmd, tableView,section):
    key = list(data.keys())[section]
    return ns(len(data[key])).integerValue()

def sectionIndexTitlesForTableView_(self,cmd,tableView):
    return ns(list(data.keys())).ptr

def tableView_sectionForSectionIndexTitle_atIndex_(self,cmd,tableView,title,index):
    #I have assumed order and number of list is the same from list and sections
    return index

def tableView_titleForHeaderInSection_(self,cmd,tableView,section):
    return ns('Header for ' + list(data.keys())[section]).ptr

def tableView_viewForHeaderInSection_(self,cmd,tableView,section):
    print('ici')
    return ns('Header for ' + list(data.keys())[section]).pt

def tableView_heightForHeaderInSection_(self,cmd,tableView,section):
    return 50.0

def tableView_titleForFooterInSection_(self,cmd,tableView,section):
    return ns('Footer for ' + list(data.keys())[section]).ptr

def tableView_commitEditingStyle_forRowAtIndexPath_(self,cmd,tableView,editingStyle,indexPath):
    if editingStyle == 1:
        # delete
        section_row = ObjCInstance(indexPath)
        tv = ObjCInstance(tableView)
        row = section_row.row()
        b = console.alert('delete row',str(row), 'confirm', 'cancel', hide_cancel_button=True)
        if b == 1:
            pass
            #tv.beginUpdates()
            #?.removeAtIndex(indexPath.row)
            #tv.deleteRowsAtIndexPaths_withRowAnimation_([section_row],0)
            #tv.endUpdates()            


#def tableView_canEditRowAtIndexPath_(self,cmd,tableView,indexPath):
    #pass

#def tableView_canMoveRowAtIndexPath_(self,cmd,tableView,indexPath):
    #pass

#def tableView_moveRowAtIndexPath_toIndexPath_(self,cmd,tableView,fromIndexPath,toIndexPath):
    #pass

methods = [tableView_cellForRowAtIndexPath_,tableView_numberOfRowsInSection_,numberOfSectionsInTableView_,tableView_titleForHeaderInSection_,tableView_sectionForSectionIndexTitle_atIndex_,sectionIndexTitlesForTableView_,tableView_titleForFooterInSection_, tableView_commitEditingStyle_forRowAtIndexPath_]#, tableView_viewForHeaderInSection_, tableView_heightForHeaderInSection_]
protocols = ['UITableViewDataSource']
TVDataSourceAndDelegate = create_objc_class('TVDataSourceAndDelegate', NSObject, methods=methods, protocols=protocols)

#=============== TableView delegate: begin
def tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_(self,cmd, tableView, indexPath):
    global UISwipeActionsConfiguration
    #return None
    return UISwipeActionsConfiguration.ptr

methods = [tableView_trailingSwipeActionsConfigurationForRowAtIndexPath_]
protocols = ['UITableViewDelegate']
UITableViewDelegate = create_objc_class('UITableViewDelegate', NSObject, methods=methods, protocols=protocols)
#=============== TableView delegate: end

def handler():
    print('handler called')
    return

@on_main_thread
def Main():
        global UISwipeActionsConfiguration
        root_vc = UIApplication.sharedApplication().keyWindow().rootViewController()
        tableviewcontroller = UITableView.alloc().initWithStyle_(UITableViewStyle.UITableViewStylePlain)


        #=============== TableView delegate: begin              
        #set delegate
        tb_ds = TVDataSourceAndDelegate.alloc().init().autorelease()
        tableviewcontroller.tableView().setDataSource_(tb_ds)

        tb_dl = UITableViewDelegate.alloc().init().autorelease()
        tableviewcontroller.tableView().setDelegate_(tb_dl)

        # set actions if swipe
        UIContextualAction = ObjCClass('UIContextualAction').alloc()
        UIContextualAction.setTitle_("@Ryubai's' action 😅")
        # block does not have parameter nor return, thus we can use a Python def
        UIContextualAction.setHandler_(handler)
        UIContextualAction.setBackgroundColor_(ObjCClass('UIColor').blueColor().colorWithAlphaComponent(0.5))

        UISwipeActionsConfiguration = ObjCClass('UISwipeActionsConfiguration').configurationWithActions_([UIContextualAction])
        #=============== TableView delegate: end

        root_vc.presentViewController_animated_completion_(tableviewcontroller, True, None)

if __name__ == '__main__':
    Main()

ryubai

@cvp thank you very much.
i prefer to use uitableviewcontroller,it connect data source and delegate automatically.
your code works but when I transfer to UITableViewController,it crashs.

cvp

@ryubai said:

when I transfer to UITableViewController,it crashs.

Sorry, I don't understand "transfer"