Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Carplay - ios 14 Broken feature. CPListImageRowItem can't be used in CPListSection #9996

Closed
ghost opened this issue Oct 29, 2020 · 10 comments
Closed
Labels
bug If an issue is a bug or a pull request a bug fix iOS Issues affecting iOS need-info Waiting for more information before the bug can be investigated
Milestone

Comments

@ghost
Copy link

ghost commented Oct 29, 2020

In the carplay framework, it's impossible to use the new CPListImageRowItem from ios 14 with the current version of xamarin-ios-14.2.0.12.

In the Apple ios api, the init function for CPListSection is (NSArray<id> *)items;
Both CPListItem and CPListImageRowItem implements CPListTemplateItem via CPSelectableListItem, but the Xamarin API doesn't allow CPListTemplateItem in the constructor.

Actual Behavior

In Xamarin, CPListSection constructor is takes a CPListItem [] items, but CPListImageRowItem doesn't inherit from this interface.
Both CPListItem and CPListImageRowItem have the CPSelectableListItem interface.
We can't create a CPListSection with CPListImageRowItem

Expected Behavior

We should be able to create CPListSection with CPListTemplateItem. The binding should probably be change to make
CPListSection constructor take an array of CPListTemplateItem instead of CPListItem

Workaround

#9996 (comment)

@chamons
Copy link
Contributor

chamons commented Oct 29, 2020

So according to this the definition is:

  • (instancetype)initWithItems:(NSArray<id> *)items;

This code compiles in ObjC:

    CPListItem * item = [[CPListItem alloc] initWithText:@"Test" detailText:@"Details"];
    CPListImageRowItem * rowItem = [[CPListImageRowItem alloc] initWithText:@"Test" images:@[]];
    CPListSection * section = [[CPListSection alloc] initWithItems:@[item, rowItem]];

this code fails to compiler in C#:

			var item = new CPListItem ("Text", "Details");
			var rowItem = new CPListImageRowItem ("test", new UIImage[] { });
			var section = new CPListSection (new CPListItem[] { rowItem, section });

with

ViewController.cs(62,62): Error CS0029: Cannot implicitly convert type 'CarPlay.CPListImageRowItem' to 'CarPlay.CPListItem' (CS0029) (CarPlayAPICheck)

@chamons chamons added bug If an issue is a bug or a pull request a bug fix iOS Issues affecting iOS labels Oct 29, 2020
@chamons chamons added this to the Future milestone Oct 29, 2020
@janwiebe-jump
Copy link
Contributor

I am also encountering this issue. Is there a workaround available @rolfbjarne @chamons ? Thanks!

@chamons
Copy link
Contributor

chamons commented Jul 12, 2022

There is no great work around available, since the class hierarchy is wrong in C#.

A possible work around would be something like this:

var item = new CPListItem("Text", "Details");
var rowItem = new CPListImageRowItem("test", new UIImage[] { });
var rowItemHack = ObjCRuntime.Runtime.GetINativeObject<CPListItem>(rowItem.Handle, true, false);
var section = new CPListSection(new CPListItem[] { item, rowItemHack });

which compiles (and doesn't crash), but I don't have a CarPlay test app to test it.

What we are doing is using a low level API (GetINativeObject) along with forced_type, which tells our runtime "I know exactly what I'm doing, trust me ™️".

This is in general dangerous, because if you are wrong you'll get a native object running around in a managed object that doesn't match, and the first invocation may crash. However, in this case it should be safe, I think.

Thoughts @rolfbjarne? Am I missing something here?

@rolfbjarne
Copy link
Member

@chamons that's all correct!

@janwiebe-jump
Copy link
Contributor

@chamons Thanks so much, it works!

@janwiebe-jump
Copy link
Contributor

janwiebe-jump commented Jul 29, 2022

Hmm,
Sometimes I get a weird exception when tapping on a CPListImageRowItem image.
Any clue?

Unable to cast object of type 'CarPlay.CPListItem' to type 'CarPlay.CPListImageRowItem'.
  at ObjCRuntime.Runtime.GetNSObject[T] (System.IntPtr ptr) [0x00135] in <c07d1d2ff2fb499fb8eca9a33aeb3c2e>:0 
  at ObjCRuntime.Trampolines+SDCPListImageRowItemHandler.Invoke (System.IntPtr block, System.IntPtr item, System.nint index, System.IntPtr completionBlock) [0x00016] in /Users/builder/azdo/_work/1/s/xamarin-macios/src/build/ios/native/ObjCRuntime/Trampolines.g.cs:1635 
  at (wrapper native-to-managed) ObjCRuntime.Trampolines+SDCPListImageRowItemHandler.Invoke(intptr,intptr,System.nint,intptr)
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.Type principalClass, System.Type delegateClass) [0x0003b] in /Users/builder/azdo/_work/1/s/xamarin-macios/src/UIKit/UIApplication.cs:85 
  at FamilyStream.iOS.Application.Main (System.String[] args) [0x00001] in D:\Projecten\FamilyStream\app\FamilyStream\FamilyStream.iOS\Main.cs:17 

This is my code:

private CPListSection CreateSection()
{

	var item = new CPListImageRowItem("Title", images); // The array of images has been created before.

	item.Handler = new CPSelectableListItemHandler(ImageListRowHandler);
	item.ListImageRowHandler = new CPListImageRowItemHandler(ImageListRowItemHandler);
	try
	{
		// We need to hack a little: https://github.com/xamarin/xamarin-macios/issues/9996#issuecomment-1182188805
		var rowItem = ObjCRuntime.Runtime.GetINativeObject<CPListItem>(item.Handle, true, false);

		var section = new CPListSection(new CPListItem[] { rowItem });
		return section
	}
        catch(Exception exc)
	{
	// No exception is caught here, since it occurs on tap of the image item.
	}
}

The signature of ImageLostRowItemHandler is private void ImageListRowItemHandler(CPListImageRowItem item, nint index, Action completionHandler)

@chamons
Copy link
Contributor

chamons commented Jul 29, 2022

Hmm, that exception suggests that you have a CPListItem that is being GetINativeObject<CPListItem>'ed into a CPListImageRowItem incorrectly.

Is that the only location you have a GetINativeObject call in your code base?

Without a sample showing the issue, it will be difficult to track this down.

@chamons chamons added the need-info Waiting for more information before the bug can be investigated label Jul 29, 2022
@ghost
Copy link

ghost commented Jul 29, 2022

Hi @ghost. We have added the "need-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@chamons
Copy link
Contributor

chamons commented Jul 29, 2022

Also, in the future this really should have been a new issue.

@ghost
Copy link

ghost commented Aug 5, 2022

Hi @ghost. Due to inactivity, we will be closing this issue. Please feel free to re-open this issue if the issue persists. For enhanced visibility, if over 7 days have passed, please open a new issue and link this issue there. Thank you.

@ghost ghost closed this as completed Aug 5, 2022
janwiebe-jump added a commit to janwiebe-jump/xamarin-macios that referenced this issue Aug 5, 2022
rolfbjarne added a commit that referenced this issue Aug 22, 2022
As discussed in #9996 the CPListSection constructors are not fully correct, since the CPListImageRowItem can't be added to it, which is possible in the native iOS SDK.
This PR fixes that. With that, also #15622 seems to be fixed.

Co-authored-by: Manuel de la Pena <mandel@microsoft.com>
Co-authored-by: Alex Soto <alex@alexsoto.me>
Co-authored-by: Chris Hamons <chris.hamons@xamarin.com>
Co-authored-by: Rolf Bjarne Kvinge <rolf@xamarin.com>
@ghost ghost locked as resolved and limited conversation to collaborators Sep 4, 2022
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug If an issue is a bug or a pull request a bug fix iOS Issues affecting iOS need-info Waiting for more information before the bug can be investigated
Projects
None yet
Development

No branches or pull requests

3 participants