We've had a live app for months that worked fine, and then suddenly this code broke:
ViewController.swift
self.tableView.delegate = self.viewModel.tableViewHandler
which used this code
component.swift
public override weak var delegate: UITableViewDelegate? {
get { return super.delegate }
set {
if let del = newValue as? TableViewDelegateProxy {
super.delegate = del
} else if let del = super.delegate as? TableViewDelegateProxy {
del.targetDelegate = newValue
} else {
super.delegate = newValue
}
}
}
We couldn't figure out why, but we fixed it with this code:
ViewController.swift
self.tableView.fixedDelegate = self.viewModel.tableViewHandler
component.swift
// IMPORTANT NOTE: That is the correct way to set a delegate,
// otherwise overriding `delegate` property fails
public var fixedDelegate: UITableViewDelegate? {
get { return self.delegate }
set {
self.delegateProxy.targetDelegate = newValue
self.delegate = self.delegateProxy
}
}
Initially we thought it was a problem from the backend (malformed JSON or something like that), but then we realized the following:
We jumped back many releases in our Git history, and the same was always true, which is making us believe that there may have been some change to our Xcode or Objc/Swift runtime libraries which is causing this weirdness.
What can be changing in our Xcode IDE to explain this? Can it be something that is changing remotely or behind the scenes? How can we further debug this?
1) Xcode version: Version 10.1 (10B61)
2) Swift version:
xcrun swift -version
Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)
Target: x86_64-apple-darwin18.2.0
3) obj-c libraries:
otool -L /usr/lib/libobjc.A.dylib
/usr/lib/libobjc.A.dylib:
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libc++abi.dylib (compatibility version 1.0.0, current version 400.17.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
First see this answer, we need to turn off this flag programmatically
_serverConfiguration.isCodelessEventsEnabled
not sure how from the sdk (Android or iOS)
1) we couldn't find any way of doing this through the FB SDKs, such as this one: https://developers.facebook.com/docs/reference/androidsdk/current/facebook/com/facebook/facebooksdk.html/
2) we tried to reverse engineer contacting the FB APIs via curl, it worked for scenarios like email:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"app_events_feature_bitmask":0}' \
"https://graph.facebook.com/***?access_token=<app_secret>"
which returned this
{"success":true}
but for app events feature nothing changed:
curl -i -X GET "https://graph.facebook.com/***?fields=app_events_feature_bitmask&access_token=<app_secret>"
it returns the old value:
{"app_events_feature_bitmask":37,"id":"***"}
3) ask FB tech support
Click User our codeless event setup tool then select the app you want to add events to. Choose the platform by clicking on Start Setup. If this is your first time visiting the codeless flow you'll see a small tutorial. After the tutorial, open a new session of your app on your mobile device.
Go to the Events Manager to codelessly add app events you want to track. In the Events Manager click Add New Data Source and select App Events in the dropdown menu. Click Use our codeless event setup tool then select the app you want to add events to. Choose the platform by clicking on Start Setup.
To turn on Codeless debug event, add the following lines in AndroidManifest.xml: Go to the Events Manager to codelessly add app events you want to track. In the Events Manager click Add New Data Source and select App Events in the dropdown menu. Click Use our codeless event setup tool then select the app you want to add events to.
To turn on this option, in Unity Editor select Facebook | Edit Settings, then select Auto Logging App Events: At this point you can add App Events with Events Manager: Under Add Data Source, select App Events.
It turns out this is some facebook remote config thing, if we comment out this code:
// UITableView
void (^tableViewBlock)(UITableView *tableView,
SEL cmd,
id<UITableViewDelegate> delegate) =
^(UITableView *tableView, SEL cmd, id<UITableViewDelegate> delegate) {
if (!delegate) {
return;
}
[self matchView:tableView delegate:delegate];
};
[FBSDKSwizzler swizzleSelector:@selector(setDelegate:)
onClass:[UITableView class]
withBlock:tableViewBlock
named:@"match_table_view"];
It works just fine. This feature seems to turn on once this flag is turned on:
#if !TARGET_OS_TV
- (void)enableCodelessEvents {
if (_serverConfiguration.isCodelessEventsEnabled) { <-----
if (!_eventBindingManager) {
_eventBindingManager = [[FBSDKEventBindingManager alloc] init];
}
if ([FBSDKInternalUtility isUnity]) {
[FBSDKAppEvents sendEventBindingsToUnity];
} else {
[_eventBindingManager updateBindings:[FBSDKEventBindingManager
parseArray:_serverConfiguration.eventBindings]];
}
}
}
#endif
the question is: what turned on this flag? (ie from some fb remote config)
_serverConfiguration.isCodelessEventsEnabled
that's what we're trying to find out
Facebook tech support got back to me stating in plain english that this option is simply not possible:
So long story short: by installing FB App Events SDK you will automatically turn on the FB remote config that enables Codeless Events and there is no way to turn it off.
We were able to reproduce the problem (specifically, turning on fb remote events flag by doing several steps on the facebook admin)
when you click on that button you'll see this
and that's when the flag is turned on!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With