Files
jims-blog/blogs/creating-a-nuget-pcl-that-works-with-xamarin-ios/index.html
2023-01-21 22:30:31 +00:00

41 lines
17 KiB
HTML

<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=x-ua-compatible content="ie=edge"><link rel=icon href=/fav.png type=image/png><link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=preload as=style href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"><link rel=stylesheet href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" media=print onload='this.media="all"'><noscript><link href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet></noscript><link rel=stylesheet href=/css/font.css media=all><meta property="og:title" content="Creating a NuGet PCL that works with Xamarin.ios"><meta property="og:description" content="I&rsquo;ve been playing with Xamarin.Forms recently to develop an iOS app. The aim is to use my portable open source Plex API in the app (more details of the app will come later once it&rsquo;s ready to release).
The basic concept of Xamarin.Forms is to have a core portable class library containing all the application code, and very thin platform specific libraries that wrap the core code in an application that targets the relevant platform."><meta property="og:type" content="article"><meta property="og:url" content="https://jimbobbennett.dev/blogs/creating-a-nuget-pcl-that-works-with-xamarin-ios/"><meta property="og:image" content="https://jimbobbennett.dev/blogs/creating-a-nuget-pcl-that-works-with-xamarin-ios/banner.png"><meta property="article:section" content="blogs"><meta property="article:published_time" content="2014-08-07T06:33:27+00:00"><meta property="article:modified_time" content="2014-08-07T06:33:27+00:00"><meta property="og:site_name" content="JimBobBennett"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://jimbobbennett.dev/blogs/creating-a-nuget-pcl-that-works-with-xamarin-ios/banner.png"><meta name=twitter:title content="Creating a NuGet PCL that works with Xamarin.ios"><meta name=twitter:description content="I&rsquo;ve been playing with Xamarin.Forms recently to develop an iOS app. The aim is to use my portable open source Plex API in the app (more details of the app will come later once it&rsquo;s ready to release).
The basic concept of Xamarin.Forms is to have a core portable class library containing all the application code, and very thin platform specific libraries that wrap the core code in an application that targets the relevant platform."><meta name=twitter:site content="@jimbobbennett"><meta name=twitter:creator content="@jimbobbennett"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css integrity=sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3 crossorigin=anonymous><link rel=stylesheet href=/css/header.css media=all><link rel=stylesheet href=/css/footer.css media=all><link rel=stylesheet href=/css/theme.css media=all><link rel="shortcut icon" type=image/png href=/fav.png><link rel="shortcut icon" sizes=192x192 href=/fav.png><link rel=apple-touch-icon href=/fav.png><link rel=alternate type=application/rss+xml href=https://jimbobbennett.dev/index.xml title=JimBobBennett><script type=text/javascript>(function(e,t,n,s,o,i,a){e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)},i=t.createElement(s),i.async=1,i.src="https://www.clarity.ms/tag/"+o,a=t.getElementsByTagName(s)[0],a.parentNode.insertBefore(i,a)})(window,document,"clarity","script","dctc2ydykv")</script><style>:root{--text-color:#343a40;--text-secondary-color:#6c757d;--background-color:#000;--secondary-background-color:#64ffda1a;--primary-color:#007bff;--secondary-color:#f8f9fa;--text-color-dark:#e4e6eb;--text-secondary-color-dark:#b0b3b8;--background-color-dark:#000000;--secondary-background-color-dark:#212529;--primary-color-dark:#ffffff;--secondary-color-dark:#212529}body{background-color:#000;font-size:1rem;font-weight:400;line-height:1.5;text-align:left}</style><meta name=description content><link rel=stylesheet href=/css/index.css><link rel=stylesheet href=/css/single.css><link rel=stylesheet href=/css/projects.css media=all><script defer src=/fontawesome-5/all-5.15.4.js></script><title>Creating a NuGet PCL that works with Xamarin.ios | JimBobBennett</title></head><body class=light onload=loading()><header><nav class="pt-3 navbar navbar-expand-lg"><div class="container-fluid mx-xs-2 mx-sm-5 mx-md-5 mx-lg-5"><a class="navbar-brand primary-font text-wrap" href=/><img src=/fav.png width=30 height=30 class="d-inline-block align-top">
JimBobBennett</a>
<button class=navbar-toggler type=button data-bs-toggle=collapse data-bs-target=#navbarContent aria-controls=navbarContent aria-expanded=false aria-label="Toggle navigation"><svg aria-hidden="true" height="24" viewBox="0 0 16 16" width="24" data-view-component="true"><path fill-rule="evenodd" d="M1 2.75A.75.75.0 011.75 2h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 2.75zm0 5A.75.75.0 011.75 7h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 7.75zM1.75 12a.75.75.0 100 1.5h12.5a.75.75.0 100-1.5H1.75z"/></svg></button><div class="collapse navbar-collapse text-wrap primary-font" id=navbarContent><ul class="navbar-nav ms-auto text-center"><li class="nav-item navbar-text"><a class=nav-link href=/ aria-label=home>Home</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#about aria-label=about>About</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#projects aria-label=projects>Recent Highlights</a></li><li class="nav-item navbar-text"><a class=nav-link href=/blogs title="Blog posts">Blog</a></li><li class="nav-item navbar-text"><a class=nav-link href=/videos title=Videos>Videos</a></li><li class="nav-item navbar-text"><a class=nav-link href=/livestreams title=Livestreams>Livestreams</a></li><li class="nav-item navbar-text"><a class=nav-link href=/conferences title=Conferences>Conferences</a></li><li class="nav-item navbar-text"><a class=nav-link href=/resume title=Resume>Resume</a></li></ul></div></div></nav></header><div id=content><section id=projects><div class="container pt-5" id=list-page><div class="row justify-content-center px-3 px-md-5"><h1 class="text-left pb-2 content">Creating a NuGet PCL that works with Xamarin.ios</h1><div class="text-left content">Jim Bennett
<small>|</small>
Aug 7, 2014</div></div></div></section><section id=single><div class=container><div class="row justify-content-center"><div class="col-sm-12 col-md-12 col-lg-9"><div class=pr-lg-4><article class="page-content p-2"><p>I&rsquo;ve been playing with Xamarin.Forms recently to develop an iOS app. The aim is to use my <a href=https://github.com/jimbobbennett/ComPlexion>portable open source Plex API</a> in the app (more details of the app will come later once it&rsquo;s ready to release).</p><p>The basic concept of <a href=http://xamarin.com/forms>Xamarin.Forms</a> is to have a core portable class library containing all the application code, and very thin platform specific libraries that wrap the core code in an application that targets the relevant platform.</p><p>In principle - all very easy. The problem comes when you want to use other libraries with it. These libraries must be portable class libraries - PCLs. Again in principle, very easy. But the devil is in the details&mldr;</p><p>The main stumbling block I hit was HttpClient. The Microsoft PCL I use to access the Plex REST API. In principle this is a PCL so should work on all platforms. But it doesn&rsquo;t.
The issue is actually with Xamarin.ios. This doesn&rsquo;t support the Microsoft HTTP client, instead it uses the Mono version. This means my Plex API has to target both the MS and Mono versions - which is a problem as the namespaces are the same, and my iOS app project can&rsquo;t have a dependency to the MS version, and the Windows Phone project can&rsquo;t have a dependency to the Mono version.</p><p>My solution was to do the following:</p><ul><li>Change my code library code to not access the HTTPClient directly, but have an interface to a wrapper class.</li><li>Create a Xamarin.ios class library project that has an implementation of the interface using the Mono HTTPClient library.</li><li>Create a Windows PCL project (Windows 8, Windows Phone and Windows Phone Silverlight) that links to the source of the iOS implementation (the namespaces are the same so the source can be shared) that references the MS PCL HTTPClient NuGet package.</li></ul><p>This will spit out 3 dlls - one PCL for the core with no HTTP access, an iOS class library using the Mono HTTPClient and a Windows PCL that uses the MS HTTPClient.</p><p>Next challenge was to get this into a NuGet package. The more recent versions of NuGet have full PCL support which makes the whole thing easier.
To install the dlls into the correct targets I just had to ensure the target of the files was set to the correct location:</p><pre tabindex=0><code>&lt;files&gt;
&lt;!-- portable --&gt;
&lt;file src=&#34;..\Complexion.Portable\bin\$Configuration$\Complexion.Portable.dll&#34; target=&#34;lib\portable-net45+win+wp80+MonoAndroid10+MonoTouch10\Complexion.Portable.dll&#34; /&gt;
&lt;!-- ios --&gt;
&lt;file src=&#34;..\Complexion.Portable\bin\$Configuration$\Complexion.Portable.dll&#34; target=&#34;lib\MonoTouch10\Complexion.Portable.dll&#34; /&gt;
&lt;file src=&#34;..\Complexion.ios\bin\iPhone\$Configuration$\Complexion.ios.dll&#34; target=&#34;lib\MonoTouch10\Complexion.ios.dll&#34; /&gt;
&lt;!-- Win --&gt;
&lt;file src=&#34;..\Complexion.Portable\bin\$Configuration$\Complexion.Portable.dll&#34; target=&#34;lib\portable-net45+win+wp80\Complexion.Portable.dll&#34; /&gt;
&lt;file src=&#34;..\Complexion.Win\bin\$Configuration$\Complexion.Win.dll&#34; target=&#34;lib\portable-net45+win+wp80\Complexion.Win.dll&#34; /&gt;
&lt;/files&gt;
</code></pre><p>The core portable library is output to a fully portable target, as well as to individual targets for iOS and Windows. The individual platform specifi dlls are then output to specific targets. Using this setup, if I install this package to a portable project, just Complexion.Portable is installed. If it&rsquo;s for iOS (MonoTouch) then Complexion.Portable and Complexion.ios is installed. Similarly for Windows 8/Windows Phone Complexion.Portable and Complexion.Win gets installed.</p><p>The final addition was dependencies. For the portable dll there are no other dependencies. For ios there are also no additional dependencies as the Mono HTTPClient is available in the default Xamarin.iOS references. Windows is different though - it needs the Microsoft HTTPClient NuGet package installed.
Thankfully <a href=http://docs.nuget.org/docs/reference/nuspec-reference#Specifying_Dependencies_in_version_2.0_and_above>NuGet now supports dependencies by different targets</a>. Groups can be defined with a target attribute and these are only installed into projects that match the target. This means I can add groups for the different windows targets that have the Microsoft HTTPClient dependency, and nothing will be installed for other platforms.</p><pre tabindex=0><code>&lt;dependencies&gt;
&lt;group targetFramework=&#34;net45&#34;&gt;
&lt;dependency id=&#34;Microsoft.Bcl&#34; version=&#34;1.1.9&#34; /&gt;
&lt;dependency id=&#34;Microsoft.Bcl.Build&#34; version=&#34;1.0.14&#34; /&gt;
&lt;dependency id=&#34;Microsoft.Net.Http&#34; version=&#34;2.2.22&#34; /&gt;
&lt;/group&gt;
&lt;group targetFramework=&#34;win&#34;&gt;
&lt;dependency id=&#34;Microsoft.Bcl&#34; version=&#34;1.1.9&#34; /&gt;
&lt;dependency id=&#34;Microsoft.Bcl.Build&#34; version=&#34;1.0.14&#34; /&gt;
&lt;dependency id=&#34;Microsoft.Net.Http&#34; version=&#34;2.2.22&#34; /&gt;
&lt;/group&gt;
&lt;group targetFramework=&#34;wp80&#34;&gt;
&lt;dependency id=&#34;Microsoft.Bcl&#34; version=&#34;1.1.9&#34; /&gt;
&lt;dependency id=&#34;Microsoft.Bcl.Build&#34; version=&#34;1.0.14&#34; /&gt;
&lt;dependency id=&#34;Microsoft.Net.Http&#34; version=&#34;2.2.22&#34; /&gt;
&lt;/group&gt;
&lt;/dependencies&gt;
</code></pre><p>Check out <a href=https://github.com/jimbobbennett/ComPlexion>my GitHub project</a> for the full API code nuspec file.</p></article></div></div><div class="col-sm-12 col-md-12 col-lg-3"><div class=sticky-sidebar><aside class=toc><h5>Table Of Contents</h5><div class=toc-content><nav id=TableOfContents></nav></div></aside><aside class=tags><h5>Tags</h5><ul class="tags-ul list-unstyled list-inline"><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/technology target=_blank>Technology</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/ios target=_blank>iOS</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/xamarin target=_blank>xamarin</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/nuget target=_blank>nuget</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/xamarin.ios target=_blank>xamarin.ios</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/pcl target=_blank>pcl</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/nuspec target=_blank>nuspec</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/httpclient target=_blank>httpclient</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/portable-class-library target=_blank>portable class library</a></li></ul></aside></div></div></div><div class=row><div class="col-sm-12 col-md-12 col-lg-9 p-4"><div id=disqus_thread></div><script>var disqus_config=function(){this.page.url="https://jimbobbennett.dev/blogs/creating-a-nuget-pcl-that-works-with-xamarin-ios/",this.page.identifier="c9ca337a8a6ba71bbfbc95b0ba49b997"};(function(){if(window.location.hostname=="localhost")return;var e=document,t=e.createElement("script");t.src="https://jimbobbennett.disqus.com/embed.js",t.setAttribute("data-timestamp",+new Date),(e.head||e.body).appendChild(t)})()</script><noscript>Please enable JavaScript to view the <a href=https://disqus.com/?ref_noscript>comments powered by Disqus.</a></noscript></div></div></div><button class="p-2 px-3" onclick=topFunction() id=topScroll>
<i class="fas fa-angle-up"></i></button></section><script>var topScroll=document.getElementById("topScroll");window.onscroll=function(){scrollFunction()};function scrollFunction(){document.body.scrollTop>20||document.documentElement.scrollTop>20?topScroll.style.display="block":topScroll.style.display="none"}function topFunction(){document.body.scrollTop=0,document.documentElement.scrollTop=0}</script></div><footer><div class="container py-4"><div class="row justify-content-center"><div class="col-md-4 text-center">&copy; 2023 All Rights Reserved</div></div></div></div></footer><script src=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js integrity=sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13 crossorigin=anonymous></script>
<script>document.body.className.includes("light")&&(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))</script><script>let loadingIcons;function loading(){myVar=setTimeout(showPage,100)}function showPage(){try{document.getElementById("loading-icons").style.display="block"}catch{}}</script><script>function createCopyButton(e,t){const n=document.createElement("button");n.className="copy-code-button",n.type="button",n.innerText="Copy",n.addEventListener("click",()=>copyCodeToClipboard(n,e,t)),addCopyButtonToDom(n,e)}async function copyCodeToClipboard(e,t,n){const s=t.querySelector("pre > code").innerText;try{n.writeText(s)}finally{codeWasCopied(e)}}function codeWasCopied(e){e.blur(),e.innerText="Copied!",setTimeout(function(){e.innerText="Copy"},2e3)}function addCopyButtonToDom(e,t){t.insertBefore(e,t.firstChild);const n=document.createElement("div");n.className="highlight-wrapper",t.parentNode.insertBefore(n,t),n.appendChild(t)}if(navigator&&navigator.clipboard)document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,navigator.clipboard));else{var script=document.createElement("script");script.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard-polyfill/2.7.0/clipboard-polyfill.promise.js",script.integrity="sha256-waClS2re9NUbXRsryKoof+F9qc1gjjIhc2eT7ZbIv94=",script.crossOrigin="anonymous",script.onload=function(){addCopyButtons(clipboard)},document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,script)),document.body.appendChild(script)}</script></body></html>