Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Admob Framework class not detected by Xcode interface builder

I've been trying to implement native Google adMob ads in my iOS app and followed the admob official tutorial: https://developers.google.com/admob/ios/native/advanced

Whether I added the required admob framework manually or by CocoaPods, all the classes in the admob frameworks were not detected by the interface builder, so I could not set the Custom class of UIView to the wanted admob view classes. But weirdly I could use all the admob-related classes after the framework was imported in my swift files. See the below screenshot:

enter image description here

enter image description here

I found a github project, which did nothing but just implmented the admob native ad by Cocoapoding the admob framework (project link). I downloaded its source code and oddly the admob framework classes can be detected by interface face in this project.

enter image description here

I've been scratching my heads for a couple days and searching for the solution without luck. Please help me out if you have a clue why this happened and your help is highly apprecaited.

like image 868
marcel Avatar asked Feb 24 '21 04:02

marcel


2 Answers

TL;DR

Downgrade the CocoaPods pod version to 7.67.0. (-:

Podfile

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

Explanation

This is because GoogleMobileAds.framework became GoogleMobileAds.xcframework in 7.68.0+ - source. This means that the Objective C runtime differs between the framework (iOS 9) and the main target (iOS 14.0+). XCFrameworks are a special type of binary framework, so editing the iOS version manually after it has already been compiled won't make a difference, and in fact, even if you specify an iOS version in your Podfile it won't make a difference.

The main code has a different, faster Objective-C runtime under the hood, and so tracks classes using different data structures to the XCFramework. For example, if a category is defined in the framework, that will be stored in read-write memory even if the new overridden method isn't used (at runtime). On the other hand, the Objective-C runtime in iOS 14.0+ doesn't load these methods until they are used to save RAM. This is a breaking change for old iOS versions because the old data structures used to index these classes no longer include the category methods (in the same storage area) and dependent logic (that reads these data structures) in the framework will no longer work. Method swizzling is handled differently and this is what GoogleUtilities does as well (a dependency of GoogleMobileAds) so this can cause issues. So even if IB Autocomplete doesn't work (no big issue there), the class won't be found dynamically at runtime. I haven't mentioned changes to method list representation changes under the hood in the new runtime since that is out of scope for this question, but old method lists will still be usable at runtime (non-breaking change).

To work around this, just use the 7.67.0 version in your Podfile for now. You can't do anything else about this as an end-user of the framework, since the podspec specifies the framework type as a vendored_framework and this is only editable within the framework's source code. I tried to disable use_frameworks but that doesn't compile. If you can edit the podspec for your own frameworks, changing to a static framework is a viable solution (with caveats). The framework get linked at build time instead of load time for static frameworks so you should be able to see the framework class in IB, but then you have to make the dependent pods of the framework also static (more work). The easier equivalent is to just downgrade the pod, or disabling use_frameworks in the Podfile. However, frameworks have faster performance (linking time) and are generally preferred which is why they are enabled by default for CocoaPods.

I would also have suggested making a new GitHub Issue for this bug, but it looks like the SDK is not open-source. Maybe this bug will be resolved by Apple in the future, or by Google once they become aware of it but this is a workaround for now.

like image 100
Pranav Kasetti Avatar answered Sep 23 '22 02:09

Pranav Kasetti


According to Google Developer in this 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.

I am successfully able to get the outlets following this workaround.

Here's what you need to do

  1. Copy the contents of the file GADNativeAd.h. You can open this file by setting the class of a view in IB as GADNativeAdView. Then click on the disclosure arrow to open the class. Make sure to change it back to whatever it was originally.

enter image description here

  1. Now create a new file i.e header file. Name it GADNativeAd.h.

  2. Paste the contents of that file in this newly created file.

  3. Build the project once.

You should now be seeing the outlets in your xib's Connection Inspector.

Refrain from falling back to a working version as iOS ATT changes won't be present in them.

like image 31
Rishab Avatar answered Sep 25 '22 02:09

Rishab