Problem with declares

Have this function that gets previously selected row in a table that was pushed off for new screen. Pressing back this is supposed to hilight the same row the user was on.

This is more than a few years old and this function now crashes the app.

Function RecallSelectedRow(iTable as iOSTable, lnRow As Integer, lnSection as Integer = 0)
'if lnRow = 0 then lnRow = -1

Declare Function NSClassFromString Lib "Foundation" (classname As CFStringRef) As Ptr

// And this one to create an instance
Declare Function alloc Lib "Foundation" selector "alloc" (classRef As Ptr) As Ptr

// Create an instance of NSIndexPath with the row to select

// Get pointer to class
Dim NSIndexPath As Ptr = NSClassFromString("NSIndexPath")

// Create an instance
Dim rowPath As Ptr = alloc(NSIndexPath)

// Now initialize it with initWithIndex:(NSUInteger)index
// Note the trailing ":" is very important!
Declare Sub initPath Lib "Foundation" Selector "initWithIndex:" (id As Ptr, row As UInteger)
initPath(rowPath, lnSection)

// Append the row and get back a new IndexPath with both
// (NSIndexPath *)indexPathByAddingIndex:(NSUInteger)index
Declare Function addIndex Lib "Foundation" Selector "indexPathByAddingIndex:" (id As Ptr, row As UInteger) As Ptr
Dim fullPath As Ptr
fullPath = addIndex(rowPath, lnRow)   '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Crashes here.

// This is the correct initializer to use since we need two indexes
// Declare Sub initPath Lib "Foundation" Selector "initWithIndexes:length:" (id As Ptr, rows As Ptr, length As UInteger)
// Dim rows() As UInteger = Array(CType(0, UInteger), CType(2, UInteger)) // section, row
// initPath(rowPath, rows, rows.Ubound)

// Now that we have the index path, we can send it to the selectRow method from above
Declare Sub selectRow Lib "UIKit" Selector "selectRowAtIndexPath:animated:scrollPosition:" (id As Ptr, row As Ptr, animated As Boolean, scrollPosition As Integer)
// selectRow(Table1.Handle, rowPath, True, 0)
selectRow(iTable.Handle, fullPath, True, 0)

// This crashes. Check the console log and look at the report.
// Report says:
// *** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
// reason: 'Invalid index path for use with UITableView.
// Index paths passed to table view must contain exactly two indices specifying the section and row.
// Please use the category on NSIndexPath in UITableView.h if possible.'

// Fix index path to add the section (0)
// We'll just append it
// (NSIndexPath *)indexPathByAddingIndex:(NSUInteger)index

// Now scroll to the row in case it is off the screen
// (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath
// atScrollPosition:(UITableViewScrollPosition)scrollPosition
// animated:(BOOL)animated
Declare Sub scrollToRow Lib "UIKit" Selector "scrollToRowAtIndexPath:atScrollPosition:animated:" (id As Ptr, row As Ptr, scrollPosition As UInteger, animated As Boolean)
scrollToRow(iTable.Handle, fullPath, 0, True)

I don’t see any error in your code but I am sure of one thing: the whole Declare function/sub is buggy.

On macOS, I’ve had several cases where using a declare would lead to an exception (but no crash like you experienced) whereas I could call the same function with the same arguments in another way!

declares ARE an advanced feature and if you call into the OS with the wrong parameters or mistaken parameters you run the very real risk of crashing your process or worse - corrupting it in weird & wonderful ways that eventually lead to a crash in a totally unrelated area

Does it crash in the simulator? If so, open Console and look for the most recent crash log for the app. You may be able to get an idea from that.

While I don’t see currently where the declare is wrong – although the crash log suggests that no valid 2-index node is being built –, you might want to try to use the shortcut constructor:

Declare Function indexPathForRowinSection lib "UIKit" Selector "indexPathForRow:inSection:" (classptr as ptr, row as UInteger, Section As UInteger) As Ptr Dim NewPath As Ptr = indexPathForRowinSection(NSIndexPath, lnrow, lnsection)

And then do a SelectRow with this ptr.

Answer here:

Comparing both: @Richard, did you mix section and row?

[quote=468658:@Richard Albrecht]// Now initialize it with initWithIndex:(NSUInteger)index
// Note the trailing “:” is very important!
Declare Sub initPath Lib “Foundation” Selector “initWithIndex:” (id As Ptr, row As UInteger)
initPath(rowPath, lnSection)[/quote]
The problem is here. initPath is a function, not a Sub

@Jeremie Leroy

Is the return type Integer?

I got this error in compiler:

Tools.RecallSelectedRow, line 22
This Declare Function statement is missing its return type
Declare Function initPath Lib “Foundation” Selector “initWithIndex:” (id As Ptr, row As UInteger)

@Jeremie Leroy

I pasted that code instead of what I had and got 17 errors, here a few:

Tools.RecallSelectedRow, line 3
Type “Int32” has no member named “SectionCount”
If section > table.SectionCount - 1 Or _

Tools.RecallSelectedRow, line 4
This item does not exist
section < 0 Or _

Tools.RecallSelectedRow, line 5
This item does not exist
row > table.RowCount(section) - 1 Or _