Xcode 界面生成器未检测到 Admob 框架 class

Admob Framework class not detected by Xcode interface builder

我一直在尝试在我的 iOS 应用中实现原生 Google adMob 广告,并遵循了 admob 官方教程:https://developers.google.com/admob/ios/native/advanced

无论是手动添加还是通过CocoaPods添加所需的admob框架,界面生成器都没有检测到admob框架中的所有classes,所以我无法设置Custom class of UIView 到想要的 admob 视图 classes。但奇怪的是,在将框架导入我的 swift 文件后,我可以使用所有与 admob 相关的 classes。 请参阅以下屏幕截图:

我发现了一个 github 项目,它只是通过 Cocoapoding admob 框架 (project link) 实现了 admob 原生广告。我下载了它的源代码,奇怪的是 admob 框架 classes 可以被这个项目中的界面检测到。

几天来我一直在摸不着头脑并寻找解决方案,但运气不佳。如果您知道为什么会发生这种情况,请帮助我,非常感谢您的帮助。

尝试编辑 Storyboard 的 XML 来解决这个问题。

  • 右键单击故事板或界面生成器。
  • Select 查看控​​制器或查看并转到项目导航器面板和 select 打开方式-> 源代码菜单选项。
  • 添加属性 customClass="GADUnifiedNativeAdvView"

保存故事板或视图。

再次右键单击“项目导航器”面板中的 storyboard/view 条目,然后 select 打开 As->Interface Builder

希望您会看到自定义 class 名称。

TL;DR

将 CocoaPods pod 版本降级到 7.67.0。 (-:

播客文件

pod 'Google-Mobile-Ads-SDK', '7.67.0'

说明

这是因为GoogleMobileAds.framework7.68.0+-source变成了GoogleMobileAds.xcframework。这意味着 Objective C 运行时在框架 (iOS 9) 和主要目标 (iOS 14.0+) 之间不同。 XCFrameworks 是一种特殊类型的 binary framework,所以在已经编译后手动编辑 iOS 版本不会有什么不同,事实上,即使您在 Podfile 中指定了 iOS 版本,也不会有什么不同。

主代码在幕后有一个不同的、更快的 Objective-C 运行时,因此使用不同的数据结构跟踪 classes 到 XCFramework。例如,如果在框架中定义了一个类别,即使未使用新的覆盖方法(在运行时),该类别也将存储在读写内存中。另一方面,iOS 14.0+ 中的 Objective-C 运行时不会 加载这些方法,直到它们用于节省 RAM。这是旧 iOS 版本的 重大更改 因为用于索引这些 classes 的旧数据结构不再包括类别方法(在同一存储区域中) 和框架中的依赖逻辑(读取这些数据结构)将不再起作用。 Method swizzling 的处理方式不同,这也是 GoogleUtilities 所做的(GoogleMobileAds 的依赖项),因此这可能会导致问题。因此,即使 IB 自动完成不起作用(这没什么大问题),class 也不会在运行时动态找到。我没有提到在新运行时中对 method list 表示更改的更改,因为这超出了这个问题的范围,但是旧方法列表在运行时仍然可用(不间断变化).

要解决此问题,请暂时在 Podfile 中使用 7.67.0 版本。作为框架的 最终用户 ,您 不能对此做任何其他事情,因为 podspec 将框架类型指定为a vendored_framework 这只能在框架的源代码中编辑。我试图禁用 use_frameworks 但无法编译。如果您可以为自己的框架编辑 podspec,则更改为静态框架是一个可行的解决方案(有警告)。框架在构建时链接而不是静态框架的加载时,因此您应该能够在 IB 中看到框架 class,但是您必须使框架的依赖 pods 也是静态的(更多的工作)。更简单的等效方法是降级 pod,或在 Podfile 中禁用 use_frameworks。但是,框架具有更快的性能(链接时间)并且通常是首选,这就是默认情况下为 CocoaPods 启用它们的原因。

我还建议为这个错误制作一个新的 GitHub Issue,但看起来 SDK 不是开源的。也许 Apple 将来会解决此错误,或者 Google 一旦他们意识到它,但 这是目前的解决方法

1: pod install —clean-install

2:打开Xcode和shift-command-k

3:关闭 Xcode 并重新打开

4:喝咖啡并等待 xcode 预构建完成

TL;DR: 7.68.0以下无法降级的SDK,打开xib作为源码,手动编辑代码设置自定义Class 并到 link 网点观看。

您可以将 class 名称直接输入到领域。

请注意,如果 class 名称未显示在下拉列表中,您无需担心。您可以直接键入它,如下面的屏幕截图所示。 (例如GADUnifiedNativeAdView

但是,您不能 link outlets to views(例如,link 您对每个原生广告的浏览量),因为您不会看到 GADUnifiedNativeAdView 中的渠道从下面的截图看。

在这种情况下,您可以通过编辑视图的源代码来link 出口。

  1. 从界面生成器中完成原生广告布局。
  2. Project Navigator 面板,right-click 视图 (*.xib) 文件和 select Open As >源代码.
  3. GADUnifiedNativeAdView / GADNativeAdView<view> 标签内,添加 <connections> 标签并为每个原生广告视图声明出口。请注意,您需要从 destination 标签中引用视图的 object ID,并自行为每个出口生成一个 object ID。

下面是一个布局四种原生广告资产(媒体、图标、标题和 body)的示例:

<?xml version="1.0" encoding="UTF-8"?>
<document ...>
    <objects>
        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="GADUnifiedNativeAdView">
            <subviews>
                <view ... id="BAF-yb-wZL" userLabel="media" customClass="GADMediaView">
                    ...
                </view>
                <view ... id="U4D-Gx-1Wm" userLabel="bottom">
                    <subviews>
                        <imageView ... id="6hd-Ad-50f" userLabel="icon">
                            ...
                        </imageView>
                        <stackView ...>
                            <subviews>
                                <label ... id="UdA-3o-ttn" userLabel="headline">
                                    ...
                                </label>
                                <label ... id="Dqe-NX-Uu2" userLabel="body">
                                    ...
                                </label>
                            </subviews>
                        </stackView>
                    </subviews>
                </view>
            </subviews>
            <!-- TODO: Add outlet connections -->
            <connections>
                <outlet property="bodyView" destination="Dqe-NX-Uu2" id="GAD-Nat-Bdy"/>
                <outlet property="headlineView" destination="UdA-3o-ttn" id="GAD-Nat-Hdl"/>
                <outlet property="iconView" destination="6hd-Ad-50f" id="GAD-Nat-Ico"/>
                <outlet property="mediaView" destination="BAF-yb-wZL" id="GAD-Nat-Mdv"/>
            </connections>
        </view>
    </objects>
</document>

重要提示:您需要为与其他类似的网点(例如XXX-YYY-ZZZ)生成一个object ID,以避免意外错误。我在上面的例子中使用了 GAD-Nat-XXX 格式。

如果要查找每个插座的 属性 名称,请单击自定义 class 下拉菜单中的灰色箭头按钮。

然后,您将从 header 文件中找到出口的 属性 名称。 (例如GADUnifiedNativeAdView

重要提示:您需要至少构建一次项目才能让您的 Xcode 找到您自定义 class 的 header。

  1. Project Navigator,通过 right-clicking 视图和 selecting [使用界面生成器打开视图文件=69=]打开为 > Interface Builder XIB 文档。

  2. 在连接检查器中,确认您在上一步中添加的连接。您会看到一个警告图标,但您可以忽略它。

  1. Load and display 广告。

根据 Google 开发人员的说法 link

We are aware of this issue -- .xcframework is generally incompatible with .xib files. This is a Apple bug that we don't know when it'll get fixed.

As a temporary workaround, you could make a manual copy of the GADNativeAdView.h file to include in your project. You should then see all the outlets appearing in Interface Builder as expected.

按照这个解决方法,我成功地获得了插座。

这是您需要做的

  1. 复制文件内容GADNativeAd.h。您可以通过在 IB 中将视图的 class 设置为 GADNativeAdView 来打开此文件。然后点击披露箭头打开class。确保将其改回原来的样子。

  1. 现在创建一个新文件即头文件。将其命名为 GADNativeAd.h.

  2. 将该文件的内容粘贴到这个新创建的文件中。

  3. 构建一次项目。

您现在应该可以在 xib 的连接检查器中看到插座。

避免退回到工作版本,因为 iOS ATT 更改不会出现在其中。