How can I prevent Slate TileView Memory Access errors?

Hello when selecting items by clicking on them in a STileView widget I get a crash on line 267 of STableRow.h The error is Access violation reading location… This line triggers the error when accessing MyItem.

OwnerWidget->Private_SetItemSelection( *MyItem, true, true );

The tileview widget displays items fine and the actors are alive in the game it just selecting that causes the error. Not sure what im doing wrong or if i can use TWeakObjectPtr with STileView or what? Hopefully its a simple mistake on my part

Here is a simplified Widget that is basically what im doing. The TArray> comes from another class and gets copied into the member TArray Items of the widget.

Code:

class SGroupControllerWidget : public SCompoundWidget
{
	SLATE_BEGIN_ARGS(SGroupControllerWidget)
	{}
	SLATE_ARGUMENT(TWeakObjectPtr<AGameHUD>, OwnerHUD)

	SLATE_END_ARGS()

public:

	void Construct(const FArguments& InArgs);
	void RefreshList();

private:


	TSharedPtr<STileView<TWeakObjectPtr<AActor>>> TileViewWidget;
	TArray<TWeakObjectPtr<AActor>> Items;
	TSharedRef<ITableRow> OnGenerateTile(TWeakObjectPtr<AActor> Item, const TSharedRef<STableViewBase>& OwnerTable);

	
};

.cpp

  void SGroupControllerWidget::Construct(const FArguments& InArgs)
    {
    	OwnerHUD = InArgs._OwnerHUD;
    	this->GroupController = OwnerHUD->GetGroupController();
    	this->GroupController->OnControlGroupChanged.AddRaw(this, &SGroupControllerWidget::RefreshList);
    	this->UIResources = FUIResources::Get();
    	this->HUDStyle = &this->UIResources->GetWidgetStyle<FHUDStyle>("/Styles/HUDStyle");
    
    
    	ChildSlot
    		.VAlign(VAlign_Fill)
    		.HAlign(HAlign_Fill)
    		[
    			SNew(SBox)
    			.Padding(FMargin(30.0f, 10.0f))
    			.WidthOverride(1000.0f)
    			[
    				SNew(SHorizontalBox)
    				+ SHorizontalBox::Slot()
    				[
    					SNew(SVerticalBox)
    					+ SVerticalBox::Slot()
    						[
    							SAssignNew(this->TileViewWidget, STileView<TWeakObjectPtr<AActor>>)
    							.ListItemsSource(&Items)
    							.OnGenerateTile(this, &SGroupControllerWidget::OnGenerateTile)
    						]
    				] // end horizontal slot
    			] //end border
    		]; //end childslot
    }
    
    void SGroupControllerWidget::RefreshList()
    {
    	if (this->GroupController.IsValid() && this->TileViewWidget.IsValid())
    	{
    		TArray<TWeakObjectPtr<AActor>>* Actors = this->GroupController->GetSelectedGroup();
		        if (Actors)
		        {
			        this->Items = *(Actors);
		        }
              else
              {
                     this->Items.Empty();
              }
              this->TileViewWidget->RequestListRefresh();
    	}
    }
        
     TSharedRef<ITableRow> SGroupControllerWidget::OnGenerateTile(TWeakObjectPtr<AActor> Item, const TSharedRef<STableViewBase>& OwnerTable)
        {
        	// just a test method for demonstration purposes.
        	ABaseCharacter* Character = Cast<ABaseCharacter>(Item.Get());
        	if (Character)
        	{
        		return SNew(STableRow< TSharedPtr<SWidget> >, OwnerTable)
        			[
        				SNew(STextBlock).Text(TAttribute<FString>(FString::FromInt(Character->GetHealth())))
        			];
        	}
        	else
        	{
        		return SNew(STableRow< TSharedPtr<SWidget> >, OwnerTable)
        			[
        				SNew(STextBlock).Text(TAttribute<FString>(TEXT("UNKNOWN Type")))
        			];
        	}
        
        	
        }

I am getting the same error with an array of FStrings. Bumping for visibility.

#Implement Selection Event?

You implemented the OnGenerateTile Event

.OnGenerateTile(this, &SGroupControllerWidget::OnGenerateTile)

but it does not look like you’ve implemented your own version of the Selection Event!

Try making your own function to handle selection and see what happens!

#Implement These

	, _OnMouseButtonDoubleClick()
	, _OnSelectionChanged()

try implementing both of these and adding UE_LOG info inside your custom implementation

or you may find the issue goes away once you implement your own version of the event.

use the same general format you used for OnGenerateTile :slight_smile:

Search the code base for SSlateView for more info on exact function parameters

Rama

Hey Rama,

I added handlers for those events and unfortunatly it does not solve the issue. I also tried setting the selection mode to single (its multi by default) but no matter what anytime in STableRow OnMousebuttonDown method it still crashes whenever it calls this OwnerWidget->Private_SetItemSelection( *MyItem, true, true );

I do have another TileViewWidget with a TArray of TSharedPtrs to a custom struct. In that case I intialize the structs with new and wrap in MakeShareable then add them to the TArray. That widget works fine with or without handlers and never errors out.

The problem seems to be when using TWeakObjectPtr.

Ok I finally figured this out after debugging the hell out of engine source. Boy do I feel dumb now haha! Basically the problem was my STableRow widget that gets created in OnGenerateTile had the wrong Template type and thus my Item of type TWeakObjectPtr < AActor > was being cast to a TSharedPtr < SWidget > which is undefined of course.

Here is my updated OnGenerateTile method that works now without errors

TSharedRef<ITableRow> SGroupControllerWidget::OnGenerateTile(TWeakObjectPtr<AActor> Item, const TSharedRef<STableViewBase>& OwnerTable)
{
	// just a test method for demonstration purposes.
	ABaseCharacter* Character = Cast<ABaseCharacter>(Item.Get());
	if (Character)
	{
		return SNew(STableRow< TWeakObjectPtr<AActor> >, OwnerTable)
			[
				SNew(SCharacterTileWidget).OwnerHUD(this->OwnerHUD).Character(Character)
			];
	}
	else
	{
		return SNew(STableRow< TWeakObjectPtr<AActor> >, OwnerTable)
			[
				SNew(STextBlock).Text(TAttribute<FString>(TEXT("UNKNOWN Type")))
			];
	}
	
}