個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Microsoft MVP for Developer Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

Swift, Objective-C を Xamarin.iOS に移植する際のポイント(2) UIView.Layerの差し替え

はじめに

こんにちは、@hiro128_777です。

前回は、Swift のコードPhotoCaptureDelegate.swiftのコールバックメソッドの実装部分を移植しました。

hiro128.hatenablog.jp

今回は、PreviewView.swiftを Xamarin.iOS へ移植していきましょう。

PreviewView.swift の Xamarin.iOS への移植

では早速swiftのコードを見てみましょう。

Swift

import UIKit
import AVFoundation

class PreviewView: UIView {
    var videoPreviewLayer: AVCaptureVideoPreviewLayer {
        guard let layer = layer as? AVCaptureVideoPreviewLayer else {
            fatalError("Expected `AVCaptureVideoPreviewLayer` type for layer. Check PreviewView.layerClass implementation.")
        }
        
        return layer
    }
    
    var session: AVCaptureSession? {
        get {
            return videoPreviewLayer.session
        }
        set {
            videoPreviewLayer.session = newValue
        }
    }
    
    // MARK: UIView
    
    override class var layerClass: AnyClass {
        return AVCaptureVideoPreviewLayer.self
    }
}

今回、新しく出てきた文法は、override class var layerClass: AnyClass { return AVCaptureVideoPreviewLayer.self }です。

これを Xamarin.iOS に移植するのは少々厄介です。特殊な表現をするので知識として知らないと移植できません。

通常、UIViewLayerは自動的に作成され割り当てられます。
デフォルトではLayerCALayerインスタンスになりますが、override することでCALayer派生の任意の型を使用できます。

Xamarin.iOS で同じことを実現するには、using ObjCRuntime;を追加し、CALayer派生の任意の型を返す静的メソッド、またはプロパティを作成し、[Export("layerClass")]を設定します。

具体的には下記のようになります。

C#

public static Class LayerClass
{
    [Export("layerClass")]
    get
    {
        return layerClass = layerClass ?? new Class(typeof(AVCaptureVideoPreviewLayer));
    }
}

または

[Export ("layerClass")]
public static Class GetLayerClass ()
{
    return new Class(typeof(AVCaptureVideoPreviewLayer));
}

このあたりを詳しくご理解したい場合は、以下の公式ドキュメントを参照してください。
docs.microsoft.com


あとは、そのまま移植するだけです。

using System;

using UIKit;
using Foundation;
using AVFoundation;
using ObjCRuntime;

namespace AVCapture
{
    [Register("PreviewView")]
    public class PreviewView : UIView
    {
        static Class layerClass;

        public static Class LayerClass
        {
            [Export("layerClass")]
            get
            {
                return layerClass = layerClass ?? new Class(typeof(AVCaptureVideoPreviewLayer));
            }
        }

        public AVCaptureSession Session
        {
            get
            {
                return VideoPreviewLayer.Session;
            }
            set
            {
                VideoPreviewLayer.Session = value;
            }
        }

        public AVCaptureVideoPreviewLayer VideoPreviewLayer
        {
            get
            {
                return (AVCaptureVideoPreviewLayer)Layer;
            }
        }

        public PreviewView()
            : base()
        {
        }

    }
}

layerClass の移植方法さえ知っていればあとは非常に簡単です。

今回はここまでです。
 


次回はこちらからどうぞ!
hiro128.hatenablog.jp