Bug 23372 - UIPopoverPresentationController missing "popoverBackgroundViewClass" property
Summary: UIPopoverPresentationController missing "popoverBackgroundViewClass" property
Status: VERIFIED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 8.0.0
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-09-25 11:11 UTC by bilal.durrani
Modified: 2014-11-28 05:59 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Comment 1 Sebastien Pouliot 2014-09-25 14:51:17 UTC
`popoverBackgroundViewClass` is internal, since we avoid exposing `Class`, but it looks like the Type-based code was not part of the build.

`UIPopoverBackgroundViewMethods` is also internal, maybe because it only had static methods (which is impossible to implement as interfaces in C#). I'll verify that
Comment 2 bilal.durrani 2014-09-29 11:51:38 UTC
Is there an ETA on when these will be added to the API?

Thanks
Comment 3 Sebastien Pouliot 2014-09-30 10:56:32 UTC
@Bilal ETA is XI 8.4 (as 8.2 is frozen and will be released soon).

Support for popoverBackgroundViewClass added in master / 94f05b7668b902303dca780e7164d2b0317781d1

QA: unit tests added in same revision
Comment 4 Sebastien Pouliot 2014-09-30 11:17:26 UTC
UIPopoverBackgroundViewMethods exposed in master / 2a4a418ce72e74b07b6b7003168ff997265de878
Comment 5 Adam Kemp 2014-10-27 11:19:30 UTC
I don't see this in Xamarin.iOS 8.4. Did it slip?
Comment 6 Sebastien Pouliot 2014-10-27 11:30:42 UTC
The iOS 8.1 release required us to do an out-of-sync release (and re-number releases). IOW:

* XI 8.4 was not from master (where the fix is) but from 8.2 (branch) + iOS8.1 additions.
* XI 8.6 is now the (next) revision planned out of master.

If needed I can share some code that would expose it for you.
Comment 7 Adam Kemp 2014-10-27 11:36:54 UTC
That would help. We're kind of being forced to switch to this API so I'm trying to keep things working as they were before. I'm ok with using a hack until the property is in a stable release.
Comment 8 Adam Kemp 2014-10-28 12:48:37 UTC
Did you figure out how I could access this property in the meantime? I got this far (adapted from the UIPopoverController binding):

        private IntPtr _popoverBackgroundViewClass = IntPtr.Zero;
        public Type BackgroundViewType
        {
            get
            {
                IntPtr popoverBackgroundViewClass = _popoverBackgroundViewClass;
                if (popoverBackgroundViewClass == IntPtr.Zero)
                {
                    return null;
                }
                return MonoTouch.ObjCRuntime.Class.Lookup(_popoverBackgroundViewClass);
            }
            set
            {
                _popoverBackgroundViewClass = ((!(value == null)) ? MonoTouch.ObjCRuntime.Class.GetHandle(value) : IntPtr.Zero);
            }
        }

The problem is the Lookup function, which is internal. Is there any public way to get the C# Type for a given Objective-C Class handle?
Comment 9 Adam Kemp 2014-10-28 13:59:31 UTC
Ok, I came up with something that works. I abandoned my attempts at using the Type, and instead I just use the registered name of the class (for now). Here is my code for anyone who might need it:

        private string _backgroundViewType;
        public string BackgroundViewType
        {
            get
            {
                return _backgroundViewType;
            }
            set
            {
                _backgroundViewType = value;

                UpdateBackgroundViewType();
            }
        }

        private static readonly Selector BackgroundViewClassGetSelector = new Selector("popoverBackgroundViewClass");
        private static readonly Selector BackgroundViewClassSetSelector = new Selector("setPopoverBackgroundViewClass:");
        private IntPtr PopoverBackgroundViewClass
        {
            get
            {
                return Messaging.IntPtr_objc_msgSend(PopoverPresentationController.Handle, BackgroundViewClassGetSelector.Handle);
            }

            set
            {
                Messaging.IntPtr_objc_msgSend_IntPtr(PopoverPresentationController.Handle, BackgroundViewClassSetSelector.Handle, value);
            }
        }

        private void UpdateBackgroundViewType()
        {
            var controller = PopoverPresentationController;
            if (controller != null)
            {
                PopoverBackgroundViewClass = ((_backgroundViewType != null) ? Class.GetHandle(_backgroundViewType) : IntPtr.Zero);
            }
        }

This only works if you use a [Register] attribute for the class you want to use, and you have to supply the string that you use for that attribute.
Comment 10 Sebastien Pouliot 2014-10-28 14:04:20 UTC
Lookup is not exposed since it depends on the registrar being used (old/new + static/dynamic) so it needs a bit more (reflection) code to get it to work.

You can use those helpers to achieve the same (as newer XI will do):

		static Type GetType (UIPopoverPresentationController c)
		{
			var p = Messaging.IntPtr_objc_msgSend (c.Handle, Selector.GetHandle ("popoverBackgroundViewClass"));
			if (p == IntPtr.Zero)
				return null;
			var field = typeof(Runtime).GetField ("Registrar", BindingFlags.NonPublic | BindingFlags.Static);
			var registrar = field.GetValue (null);
			var lookup = registrar.GetType ().GetMethod ("Lookup");
			return (Type) lookup.Invoke (registrar, new object [] { p, false });
		}

		static void SetType (UIPopoverPresentationController c, Type t)
		{
			IntPtr p = t == null ? IntPtr.Zero : Class.GetHandle (t);
			Messaging.void_objc_msgSend_IntPtr (c.Handle, Selector.GetHandle ("setPopoverBackgroundViewClass:"), p);
		}
Comment 11 Akhilesh kumar 2014-11-27 08:38:01 UTC
Hi Sebastien,

I have checked this issue and observed that property  ‘PopoverBackgroundViewType’ has been added in class UIPopoverPresentationController. 
Screencast: http://screencast.com/t/ixU552Bv5Cy

And I have also verified that property 'popoverBackgroundViewClass' has been implemented in class 'UIPopoverPresentationController'.

And when I tried to verify the implementation of 'UIPopoverBackgroundViewMethods' in class 'UIPopoverPresentationController' in assembly browser then I am not getting any method with name 'UIPopoverBackgroundViewMethods' in class 'UIPopoverPresentationController'. 

To verify this I have created an object of class 'UIPopoverPresentationController' and when I type class object and press dot(.) then it is not showing method named 'UIPopoverBackgroundViewMethods' in intellisence window.
Screencast: http://screencast.com/t/zXZhI6sg1

Could you please provide some steps/instructions so that I can verify the implementation of "UIPopoverBackgroundViewMethods".

Thanks!
Comment 12 Sebastien Pouliot 2014-11-27 09:53:45 UTC
@Akhilesh

> Also missing is the protocol UIPopoverBackgroundViewMethods

^ because it's a protocol and not a method
Comment 13 Akhilesh kumar 2014-11-27 13:09:39 UTC
Thanks Sebastien

Can I verify this issue at our end? 
Actually I am not sure where should I check that protocol "UIPopoverBackgroundViewMethods".
Comment 14 Sebastien Pouliot 2014-11-27 17:22:00 UTC
Since it's a protocol you'll see an interface like this in monotouch.dll:

namespace MonoTouch.UIKit
{
	[Protocol (Name = "UIPopoverBackgroundViewMethods", WrapperType = typeof(UIPopoverBackgroundViewMethodsWrapper)), Since (8, 0)]
	public interface IUIPopoverBackgroundViewMethods : INativeObject, IDisposable
	{
	}
}
Comment 15 Akhilesh kumar 2014-11-28 05:59:48 UTC
@Sebastien: Thank you very much for your kind help.

I am getting this protocol interface for both Unified API and Classic API. 

Screencast: 
For Classic API: http://screencast.com/t/dAOfrsv1P
For Unified API: http://screencast.com/t/QH5EuGdoqC

Hence, closing this issue.