Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 77050

c.Delegate = null; crashes App on iOS < 8

$
0
0

Hey guys,

I am using Xamarin Forms to develop an App as part of my master thesis.
Now I got stuck with an iPhone 4 and iOS 7.1.
With iOS 8 and 8.4 @ iPhone 6 everything works like a charm.
Also on the Android device, but that's not relevant here.

This is the exception:

Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[UIKit_UIScrollView__UIScrollViewDelegate tableView:heightForRowAtIndexPath:]: unrecognized selector sent to instance 0xb41ffa0

I figured out that the UIScrollView is my custom ListView which enables my XF PCL App to animate a header smoothly and provide some sort of parallax effect to effectively use the full screen for my list.

If I don't use my custom iOS Renderer for that list everything works just fine.
The underlying issue comes with these two lines c.Delegate = null; and c.Scrolled += this.OnScroll;

As you can see I am setting the Delegate to null. The reason for this is, that c.Scrolled += this.OnScroll; would lead to an exception:
System.InvalidOperationException: Event registration is overwriting existing delegate. Either just use events or your own delegate: UIKit.UITableViewDelegate UIKit.UIScrollView+_UIScrollViewDelegate

Sadly I have no clue what I could do to cope with this exception or figure out the right way to enable my ListViewRenderer to listen for OnScroll-Events.
Of course I tried to do something in this fashion c.Delegate = new UITableViewDelegate(); but this will also throw an exception.

The entire class:

using System;
using System.Linq;
using CoreGraphics;
using KinsmenApp.iOS.Renderer;
using KinsmenApp.Views.UserControls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof (LazyLoadingListView), typeof (LazyLoadingListViewRenderer))]

namespace KinsmenApp.iOS.Renderer
{
    public class LazyLoadingListViewRenderer : ListViewRenderer
    {
        private CoreGraphics.CGPoint _oldOffset = new CGPoint(0, 0);

        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            var c = this.Control;

            if (c != null)
            {
                c.Delegate = null;

                c.Scrolled += this.OnScroll;
            }
        }

        protected void OnScroll(object sender, EventArgs args)
        {
            var ctrl = this.Control;
            var listView = this.Element as LazyLoadingListView;

            if (listView == null || ctrl == null || !IsVisible())
                return;

            var offset = ctrl.ContentOffset;

            var deltaX = Math.Max(_oldOffset.X, offset.X) - Math.Min(_oldOffset.X, offset.X);
            var deltaY = Math.Max(_oldOffset.Y, offset.Y) - Math.Min(_oldOffset.Y, offset.Y);
            var scrolledDown = _oldOffset.Y > offset.Y;

            listView.FireScrolledEvent(new ScrollingEventArgs(offset.X, offset.Y, deltaX, deltaY, scrolledDown));

            _oldOffset = offset;
        }

        private bool IsVisible()
        {
            var view = this.Control;
            if (view == null)
                return false;

            var cells = view.VisibleCells;
            return cells != null && cells.Any();
        }
    }
}

I'll try to write a custom delegate as it is adviced here: https://bugzilla.xamarin.com/show_bug.cgi?id=30020
But maybe someone already knows how to do it properly.

Thanks in advance for your help!


Viewing all articles
Browse latest Browse all 77050

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>