常海伦 發表於 2025-8-12 09:10:00

【Avalonia】无开发者账号利用iOS真机调试跨便捷的平台应用

<style>pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; margin: 16px 0 !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; tab-size: 4 !important; -moz-tab-size: 4 !important; max-width: 100% !important; box-sizing: border-box !important }
code { font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow-wrap: normal !important; display: inline !important; background: rgba(0, 0, 0, 0) !important; border: none !important; padding: 0 !important; margin: 0 !important; line-height: inherit !important }
pre code { background: rgba(0, 0, 0, 0) !important; border: 0 !important; border-radius: 0 !important; display: block !important; line-height: 1.6 !important; margin: 0 !important; max-width: none !important; overflow: visible !important; padding: 0 !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; color: inherit !important }
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: rgba(112, 128, 144, 1) !important; font-style: italic !important }
.token.punctuation { color: rgba(153, 153, 153, 1) !important }
.token.atrule, .token.attr-value, .token.keyword { color: rgba(0, 119, 170, 1) !important; font-weight: bold !important }
.token.function, .token.class-name { color: rgba(221, 74, 104, 1) !important; font-weight: bold !important }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: rgba(102, 153, 0, 1) !important }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: rgba(153, 0, 85, 1) !important }
.cnblogs-markdown pre, .cnblogs-post-body pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; padding: 16px !important; margin: 16px 0 !important }
pre, pre, pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important }</style>
      
<style>pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; line-height: 1.6 !important; padding: 16px !important; margin: 16px 0 !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; tab-size: 4 !important; -moz-tab-size: 4 !important; max-width: 100% !important; box-sizing: border-box !important }
code { font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14px !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; overflow-wrap: normal !important; display: inline !important; background: rgba(0, 0, 0, 0) !important; border: none !important; padding: 0 !important; margin: 0 !important; line-height: inherit !important }
pre code { background: rgba(0, 0, 0, 0) !important; border: 0 !important; border-radius: 0 !important; display: block !important; line-height: 1.6 !important; margin: 0 !important; max-width: none !important; overflow: visible !important; padding: 0 !important; white-space: pre !important; word-wrap: normal !important; word-break: normal !important; color: inherit !important }
.token.comment, .token.prolog, .token.doctype, .token.cdata { color: rgba(112, 128, 144, 1) !important; font-style: italic !important }
.token.punctuation { color: rgba(153, 153, 153, 1) !important }
.token.atrule, .token.attr-value, .token.keyword { color: rgba(0, 119, 170, 1) !important; font-weight: bold !important }
.token.function, .token.class-name { color: rgba(221, 74, 104, 1) !important; font-weight: bold !important }
.token.selector, .token.attr-name, .token.string, .token.char, .token.builtin, .token.inserted { color: rgba(102, 153, 0, 1) !important }
.token.property, .token.tag, .token.boolean, .token.number, .token.constant, .token.symbol, .token.deleted { color: rgba(153, 0, 85, 1) !important }
.cnblogs-markdown pre, .cnblogs-post-body pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; background-color: rgba(248, 248, 248, 1) !important; border: 1px solid rgba(225, 228, 232, 1) !important; border-radius: 6px !important; padding: 16px !important; margin: 16px 0 !important }
pre, pre, pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important }</style><div class="markdown_views prism-atom-one-light" id="content_views"><svg style="display: none" xmlns="http://www.w3.org/2000/svg"><path d="M5,0 0,2.5 5,5z" id="raphael-marker-block" stroke-linecap="round" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0)"></path></svg><p></p><div class="toc"><h4>文章目录</h4><ul><li>1. 要求</li><li><ul><li>1.1 无需Apple开发者账号</li><li>1.2 最新版mac系统</li><li>1.3 最新版Xcode</li></ul></li><li>2. 配对Mac</li><li>3. 配置开发证书</li><li><ul><li>3.1 创建一个名为MTClient的Xcode项目</li><li>3.2 找到签名证书</li><li>3.3 配置签名</li><li>3.4 配置标识符</li></ul></li><li>4. 真机调试</li><li><ul><li>4.1 设置应用首屏 Launch Screen</li><li>4.2 设置应用图标</li></ul></li><li>5. 问题</li><li><ul><li>5.1 DI异常</li><li><ul><li>该问题的解决</li><li><ul><li>使用`&lt;UserInterpreter&gt;`</li><li>探索MAUI</li></ul></li><li>曙光</li></ul></li><li>5.2 Could not find any available provisioning profiles for MTClient.iOS on iOS.</li><li>5.3 其他报错</li><li>5.4 Entitlements权利</li></ul></li></ul></div><p></p><h2>1. 要求</h2><h3>1.1 无需Apple开发者账号</h3><p>我这里开发的应用仅是用于调试、体验IOS应用开发流程,并没有发布到AppSotre的计划,所以没有申请一年$99的开发者账号。</p><p>但没加入开发者计划也有一些使用限制:</p><ol><li>你的应用签名有效期只有一周,到期之后需要重新把手机插到电脑上重新安装一次。</li><li>不能分发应用,多台手机的话只能一个一个装</li></ol><p>(如果你已经有了开发者账号,则可以参考这篇文章 Maui劝退:用windows直接真机调试iOS,无须和Mac配对,无需mac电脑)</p><h3>1.2 最新版mac系统</h3><p>macOS版本:15.0以上。<br> 你需要有一台装了macOS的电脑,可以是黑苹果或白苹果。(我是找了台不用的dell电脑,花了50装了最新的黑果系统)</p><p>系统最好是最新版,因为.net 9只支持macOS 15以上的版本。参见:Target Framework<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/9c3c4645fa7a42e29c4966aeec68ecd1.png"></p><h3>1.3 最新版Xcode</h3><p>AppStore安装最新的Xcode,xamarin/maui/avalonia开发的ios应用都依赖xcode。</p><h2>2. 配对Mac</h2><p>这一步比较简单,确保开发机和mac在同一个网段,vs就会自动查找到对应的mac。<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/f862fdff5093404fbac1efc50d3a32ae.png"><br> 然后点击“connect”即可,会自动在mac上安装需要的work load,大概需要十几分钟。<br> 我这里已经连接过了所以显示“disconnect”</p><h2>3. 配置开发证书</h2><blockquote><p>总体上可以参考这篇略过时的文章:如何在iPhone或iPad上构建和运行应用程序。</p></blockquote><p>也可以直接参考我的步骤:</p><h3>3.1 创建一个名为MTClient的Xcode项目</h3><p>Xcode中首先登录你的AppleID,然后创建一个名为MTClient的IOS项目。</p><p>创建有三个信息比较重要:</p><ol><li><strong>Product Name</strong>:这里的MTClient是我应用的名字,你也可以改成其它的。</li><li><strong>Organization Identifier</strong>:组织名,你用ApppleID登陆Xcode时会提示是否创建一个组织,这里自动填充的GymOrg就是我之前创建的组织。当然这里也可以用其他的组织。</li><li><strong>Bundle Identifier</strong>:<mark>核心,牢记</mark>,这个相当于你应用的标识符,后续所有的签名及证书都是基于此标识符。</li></ol><p><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/0cc95cf5c3434c9eaa3d25df25c973df.png#pic_center"><br> 创建完成后,把手机插到mac上调试下看是否能正常跑起来。</p><h3>3.2 找到签名证书</h3><p>打开SpotLight,输入KeyChainAccess:<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/e296514dc3bc4096a6adcfade5ebc1da.png#pic_center"><br> 打开<strong>钥匙串访问.app</strong>,搜索关键词develop找到刚创建的证书。<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/1b9e15e42940472d8e63d58a9f717452.png"><br> 将此证书的名字复制下来备用。</p><h3>3.3 配置签名</h3><p>首先将项目属性 Bundle Signing Scheme改为<code>Manual Provisioning</code>:<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/1353c2e53d0c439fa522ba70ca6ec938.png"><br> 然后打开项目的<code>.csproj</code>,添加<code>&lt;CodesignKey&gt;</code>,值就是之前拷贝的证书字符串。<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/8d04f85f1a664118b484f8d9e2046ed0.png"></p><h3>3.4 配置标识符</h3><p>签名配置好了,还要配置对应的应用标识符。签名+标识符才是完整的一套。<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/2400fe304642405b9ff6c4de0c6ea374.png"><br> 打开<code>info.plist</code>将Bundle Identifier改为之前我们配置的值即可。</p><h2>4. 真机调试</h2><p>这个没什么好说的,rebuild下项目,然后调试设备选择你的IOS真机,接下来就是正常的调试步骤。</p><h3>4.1 设置应用首屏 Launch Screen</h3><p>默认首屏显示的是一个白底黑字你应用名字的一个页面。<br> 你可以修改<code>LaunchScreen.xib</code>文件内容进行调整:<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/38ef4f0aa69146daa99da8332afe322a.png"><br> 同样你可以修改<code>info.plist</code>的选项以关闭首次打开时显示首屏页面:<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/6a8fb0208d204ced95ffe60981f2c7f9.png"><br> (但设置为not set后可以影响你app的展示尺寸)</p><h3>4.2 设置应用图标</h3><p>打开<code>info.plist</code>,在这里设置应用图标:<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/6766d4dc32964ed9a96d2b4f8e7379ed.png"><br> 需要多个不同宽高的图标:<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/9561aacc1ac64d1f8de526ffa406a08b.png"><br> 可使用在线工具一次性全部生成。</p><h2>5. 问题</h2><h3>5.1 DI异常</h3><p>报错 Attempting to JIT compile method 'Microsoft.Extensions.DependencyInjection.ServiceProvider :</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-shell">Received unhandled Objective-C exception that was marshalled from a managed exception: Attempting to JIT compile method <span class="token string">'Microsoft.Extensions.DependencyInjection.ServiceProvider Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions:BuildServiceProvider (Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.DependencyInjection.ServiceProviderOptions)'</span> <span class="token keyword">while</span> running <span class="token keyword">in</span> aot-only mode. See https://learn.microsoft.com/xamarin/ios/internals/limitations <span class="token keyword">for</span> <span class="token function">more</span> information.
<span class="token punctuation">(</span>System.ExecutionEngineException<span class="token punctuation">)</span>
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider<span class="token punctuation">(</span>IServiceCollection <span class="token punctuation">)</span>
at MessageTransferClient.App.OnFrameworkInitializationCompleted<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">in</span> H:<span class="token punctuation">\</span>MyProgram<span class="token punctuation">\</span>SomePractice<span class="token punctuation">\</span>Avaloni</code></pre>
<p>此问题只出现在IOS真机上,IOS模拟器、Windows、安卓都没有问题。原因是因为IOS真机不允许JIT,所以只能用AOT,但并非所有的.net 特性都支持AOT,所以就会报错。</p><p>AOT使用的一些限制具体请参考:Xamarin.iOS 的限制</p><h4>该问题的解决</h4><h5>使用<code>&lt;UserInterpreter&gt;</code></h5><p>但并不意味着所有AOT不支持的特性你都不能使用,可以参考iOS 和 Mac Catalyst 上的 Mono 解释器官方文档,在csproj中添加<code>&lt;UseInterpreter&gt;</code>。这样对于AOT不支持的特性就可以使用Mono解释器执行,缺点就是运行速度会慢一点而且也不是100%解决问题。</p><p>然而尝试使用Mono解释器后并没有解决此问题,报错变成了:</p>
<pre style="white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important"><code class="prism language-shell">Error: VTable setup of <span class="token builtin class-name">type</span> Microsoft.Extensions.DependencyInjection.ServiceProvider failed.</code></pre>
<p>解释器无法构造出DI类型所需要的函数表,网上搜了一圈也没找到如何解决。</p><p>后续我又尝试使用SimpleInject等对AOT友好的DI或者自己手写DI,但我所用到的SignalR.Client这个库严重依赖MSDI,并且无法替换。</p><h5>探索MAUI</h5><p>我曾经一度怀疑.net for ios是个鸡肋,于是在github上搜索现成的基于SignalR的MAUI开发的app,看是否都能正常工作。搜到一个之后真机调试运行了没有发现任何问题,DI也完全正常。这难道是Avalonia自身的问题?</p><p>于是乎又经历了一番尝试:将.net版本改为与MAUI中的一致、将所有用的nuget package改为与MAUI中的一致、检查plist是否一致,一番操作之后然而并没有什么用,同样的报错。</p><p>此问题遂搁置,等周末再研究。</p><h4>曙光</h4><p>于是来到了今天上午,在尝试继续解决这个问题前,我升级了下VS2022的版本,从17.10升级到了目前的最新版17.14.11。<br> 神奇的是DI就这样完全好用了,期间一个星期我没有改动过任何代码,就这么升级一下VisualStuido就解决了。不确定最终问题原因是出现了VisualStudio里还是依赖的.net9 workload里。</p><blockquote><p>关于JIT问题的两个参考链接:</p><ol><li>https://github.com/AvaloniaUI/Avalonia/discussions/19267</li><li>https://github.com/AvaloniaUI/Avalonia/issues/9934</li></ol></blockquote><h3>5.2 Could not find any available provisioning profiles for MTClient.iOS on iOS.</h3><p><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/eb12c81c2c0d4094a3a4862a02c1d0a4.png"><br> 还记得我们之前说过你的应用签名有效期只有一周吗?过了一周需要重新签。<br><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/7314b83750584bbabbb01e21633a44eb.jpeg"><br> 所以需要我们在Xcode中重新点下这个调试按钮。</p><h3>5.3 其他报错</h3><p><img alt="在这里插入图片描述" src="https://i-blog.csdnimg.cn/direct/e252e4bf3ee04ef78089d64ed31d0d3b.png"><br> 开发过程中如果你遇到了像这种奇奇怪怪本不应该报错的报错,clean–&gt;rebuild下你的IOS项目就可以了。</p><h3>5.4 Entitlements权利</h3><p>在尝试解决前面的DI问题时,我猜测可能是权利问题(但其实并不是)。所以又检索了macOS Catalina 公证以及对 .NET 下载和项目的影响这篇文章,了解了下权利。简单来说所有你准备在IOS或MAC平台上进行分发的软件都需要具备对应的权利。</p><p>但Avalonia模板创建出来的默认应用,并没有添加.net对应的权利,所以适时可以将权利添加到<code>Entitlements.plist</code>文件中。</p><hr></div><br><br>
来源:https://www.cnblogs.com/wzzkaifa/p/19033138
頁: [1]
查看完整版本: 【Avalonia】无开发者账号利用iOS真机调试跨便捷的平台应用