[iOS] Bookmarks back button A/B test + small refactoring

https://jira.mail.ru/browse/MAPSME-13249
This commit is contained in:
Alexander Boriskov 2020-08-14 16:54:07 +03:00 committed by Maksim Andrianov
parent b0cf9c86c0
commit cf9ed8fde4
23 changed files with 179 additions and 54 deletions

View file

@ -372,7 +372,7 @@ final class CatalogWebViewController: WebViewController {
let purchase = InAppPurchase.paidRoutePurchase(serverId: productInfo.id,
productId: productId)
let testGroup = PromoCampaignManager.manager().paidRoutesSubscriptionCampaign.testGroupStatName
let testGroup = ABTestManager.manager().paidRoutesSubscriptionCampaign.testGroupStatName
let stats = InAppPurchase.paidRouteStatistics(serverId: productInfo.id,
productId: productId,
testGroup: testGroup,

View file

@ -30,7 +30,7 @@ class PaidRouteViewController: MWMViewController {
private var subscription: ISubscription?
private let subscriptionManager: ISubscriptionManager
private let subscriptionType: SubscriptionGroupType
private let paidRoutesSubscriptionCampaign = PromoCampaignManager.manager().paidRoutesSubscriptionCampaign
private let paidRoutesSubscriptionCampaign = ABTestManager.manager().paidRoutesSubscriptionCampaign
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return [.portrait] }
@ -212,7 +212,7 @@ class PaidRouteViewController: MWMViewController {
}
@IBAction func onSubscribe(_ sender: UIButton) {
let type = PromoCampaignManager.manager().paidRoutesSubscriptionCampaign.actionType
let type = ABTestManager.manager().paidRoutesSubscriptionCampaign.actionType
switch type {
case .instant:
onInstantSubscribe()

View file

@ -4,6 +4,7 @@ class BookmarksBackButtonViewController: UIViewController {
private var leftOffset: NSLayoutConstraint?
private var availableArea = CGRect.zero
private var mapViewController = MapViewController.shared()
private var abTestBookingBackButtonColor = ABTestManager.manager().abTestBookingBackButtonColor
@objc var hidden: Bool = true {
didSet {
@ -11,6 +12,8 @@ class BookmarksBackButtonViewController: UIViewController {
}
}
@IBOutlet var button: MWMButton!
static var controller: BookmarksBackButtonViewController = {
guard let bookmarksBackButton = MWMMapViewControlsManager.manager()?.bookmarksBackButton else {
fatalError()
@ -20,6 +23,12 @@ class BookmarksBackButtonViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
switch abTestBookingBackButtonColor.type {
case .opaque:
button.setStyleAndApply("ButtonBookmarksBackOpaque")
default:
button.setStyleAndApply("ButtonBookmarksBack")
}
refreshLayout(false)
}
@ -62,5 +71,7 @@ class BookmarksBackButtonViewController: UIViewController {
@IBAction func buttonTouchUpInside(_ sender: Any) {
MapViewController.shared()?.bookmarksCoordinator.state = .opened
Statistics.logEvent(kStatBackClick, withParameters: [kStatFrom: kStatMap,
kStatTo: kStatBookmarks])
}
}

View file

@ -10,6 +10,7 @@
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="BookmarksBackButtonViewController" customModule="maps_me" customModuleProvider="target">
<connections>
<outlet property="button" destination="cCO-58-yy1" id="3ZH-dK-IBJ"/>
<outlet property="view" destination="cCO-58-yy1" id="67p-Rk-DQH"/>
</connections>
</placeholder>

View file

@ -65,7 +65,7 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
self.isDirectionViewHidden = YES;
self.bookmarksBackButtonHidden = YES;
self.menuRestoreState = MWMBottomMenuStateInactive;
self.promoDiscoveryCampaign = [PromoCampaignManager manager].promoDiscoveryCampaign;
self.promoDiscoveryCampaign = [ABTestManager manager].promoDiscoveryCampaign;
if (_promoDiscoveryCampaign.enabled) {
[controller.controlsView addSubview:self.promoButton];
self.promoButton.translatesAutoresizingMaskIntoConstraints = NO;
@ -280,8 +280,8 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
- (BookmarksBackButtonViewController *)bookmarksBackButton {
if (!_bookmarksBackButton) {
_bookmarksBackButton = [[BookmarksBackButtonViewController alloc] init];
[self.ownerController addChildViewController: _bookmarksBackButton];
[self.ownerController.controlsView addSubview: _bookmarksBackButton.view];
[self.ownerController addChildViewController:_bookmarksBackButton];
[self.ownerController.controlsView addSubview:_bookmarksBackButton.view];
[_bookmarksBackButton configLayout];
}
return _bookmarksBackButton;
@ -451,7 +451,7 @@ NSString *const kMapToCategorySelectorSegue = @"MapToCategorySelectorSegue";
}
- (BOOL)showPromoBookingIfNeeded {
PromoAfterBookingCampaign *afterBookingCampaign = [PromoCampaignManager manager].promoAfterBookingCampaign;
PromoAfterBookingCampaign *afterBookingCampaign = [ABTestManager manager].promoAfterBookingCampaign;
PromoAfterBookingData *afterBookingData = afterBookingCampaign.afterBookingData;
if (!afterBookingData.enabled)
return NO;

View file

@ -50,7 +50,7 @@
@objc private func onButtonPress(sender: UIButton) {
coordinator.onPromoButtonPress(completion: { [weak self] in
PromoCampaignManager.manager().promoDiscoveryCampaign.onActivate();
ABTestManager.manager().promoDiscoveryCampaign.onActivate();
self?.isHidden = true;
})
}

View file

@ -11,6 +11,7 @@ static NSString *const kStat8 = @"8";
static NSString *const kStat9 = @"9";
static NSString *const kStatAPI = @"API";
static NSString *const kStatAbout = @"About";
static NSString *const ABTestInitialized = @"ABTest_init";
static NSString *const kStatAction = @"action";
static NSString *const kStatActionSheet = @"Action sheet";
static NSString *const kStatAd = @"Ad";

View file

@ -1,13 +1,14 @@
@objc protocol IPromoCampaignManager {
@objc protocol IABTestManager {
@objc var promoDiscoveryCampaign: PromoDiscoveryCampaign { get }
@objc var promoAfterBookingCampaign: PromoAfterBookingCampaign { get }
@objc var paidRoutesSubscriptionCampaign: PaidRoutesSubscriptionCampaign { get }
@objc var abTestBookingBackButtonColor: ABTestBookingBackButtonColor { get }
}
@objc class PromoCampaignManager: NSObject, IPromoCampaignManager {
private static var shared: IPromoCampaignManager = PromoCampaignManager()
@objc class ABTestManager: NSObject, IABTestManager {
private static var shared: IABTestManager = ABTestManager()
@objc static func manager() -> IPromoCampaignManager {
@objc static func manager() -> IABTestManager {
return shared
}
@ -22,4 +23,8 @@
@objc lazy var paidRoutesSubscriptionCampaign: PaidRoutesSubscriptionCampaign = {
return PaidRoutesSubscriptionCampaign()
}()
@objc lazy var abTestBookingBackButtonColor: ABTestBookingBackButtonColor = {
return ABTestBookingBackButtonColor()
}()
}

View file

@ -1,4 +1,4 @@
@objc protocol IPromoCampaign {
@objc protocol IABTest {
init()
var enabled: Bool { get }
}

View file

@ -1,4 +1,4 @@
@objc class PaidRoutesSubscriptionCampaign: NSObject, IPromoCampaign {
@objc class PaidRoutesSubscriptionCampaign: NSObject, IABTest {
enum SubscribeActionType: Int {
case instant = 0
case window

View file

@ -1,4 +1,4 @@
@objc class PromoAfterBookingCampaign: NSObject, IPromoCampaign {
@objc class PromoAfterBookingCampaign: NSObject, IABTest {
@objc var afterBookingData: PromoAfterBookingData {
return PromoAfterBookingCampaignAdapter.afterBookingData()
}

View file

@ -1,4 +1,4 @@
@objc class PromoDiscoveryCampaign: NSObject, IPromoCampaign {
@objc class PromoDiscoveryCampaign: NSObject, IABTest {
enum Group: Int {
case discoverCatalog = 0
case downloadSamples

View file

@ -0,0 +1,43 @@
@objc class ABTestBookingBackButtonColor: NSObject, IABTest {
enum ABTestBookingBackButtonColorType: Int {
case control
case transparent
case opaque
case disabled
}
var enabled: Bool = true
private let storageKey = "\(ABTestBookingBackButtonColor.Type.self)"
private let distribution = { arc4random() % 3 }
lazy var type: ABTestBookingBackButtonColorType = {
guard enabled else {
return .disabled
}
if let stored = UserDefaults.standard.value(forKey: storageKey) as? Int,
let type = ABTestBookingBackButtonColorType(rawValue: stored) {
Statistics.logEvent(ABTestInitialized, withParameters: [kStatTestGroup: stat(type)])
return type
} else {
let rawValue = distribution()
let type = ABTestBookingBackButtonColorType(rawValue: Int(rawValue)) ?? .disabled
UserDefaults.standard.set(rawValue, forKey: storageKey)
return type
}
}()
private func stat(_ type: ABTestBookingBackButtonColorType) -> String {
switch type {
case .opaque:
return "opaque"
case .transparent:
return "transparent"
case .control:
return "transparent_control"
default:
return ""
}
}
override required init() {}
}

View file

@ -97,6 +97,10 @@ class MapStyleSheet: IStyleSheet {
s.mwmImage = "btn_back"
}
theme.add(styleName: "ButtonBookmarksBackOpaque") { (s) -> (Void) in
s.mwmImage = "btn_back_opaque"
}
theme.add(styleName: "FirstTurnView") { (s) -> (Void) in
s.backgroundColor = colors.linkBlue
s.cornerRadius = 4

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "btn_back_opaque_dark.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "btn_back_opaque_highlighted_dark.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "btn_back_opaque_highlighted_light.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "btn_back_opaque_light.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -553,8 +553,8 @@
990F33B624BC915200D0F426 /* SearchActionBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 990F33B524BC915200D0F426 /* SearchActionBarView.swift */; };
9917D17D2396793A00A7E06E /* PaidRoutesSubscriptionCampaign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9917D17C2396793A00A7E06E /* PaidRoutesSubscriptionCampaign.swift */; };
9917D17F2397B1D600A7E06E /* IPadModalPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9917D17E2397B1D600A7E06E /* IPadModalPresentationController.swift */; };
991CE2BF2371D349009EB02A /* PromoCampaignManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991CE2BA2371D349009EB02A /* PromoCampaignManager.swift */; };
991CE2C02371D349009EB02A /* PromoCampaign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991CE2BB2371D349009EB02A /* PromoCampaign.swift */; };
991CE2BF2371D349009EB02A /* ABTestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991CE2BA2371D349009EB02A /* ABTestManager.swift */; };
991CE2C02371D349009EB02A /* IABTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991CE2BB2371D349009EB02A /* IABTest.swift */; };
991CE2C22371D349009EB02A /* PromoDiscoveryCampaign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991CE2BE2371D349009EB02A /* PromoDiscoveryCampaign.swift */; };
991CE2DD2373145C009EB02A /* PromoAfterBookingCampaign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991CE2DC2373145C009EB02A /* PromoAfterBookingCampaign.swift */; };
991FCA2023B0FF33009AD684 /* AdsStyleSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991FCA1F23B0FF33009AD684 /* AdsStyleSheet.swift */; };
@ -622,6 +622,7 @@
993F5512237C622700545511 /* DeepLinkFileStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993F5504237C622700545511 /* DeepLinkFileStrategy.swift */; };
993F5513237C622700545511 /* DeepLinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993F5505237C622700545511 /* DeepLinkHandler.swift */; };
993F5514237C622700545511 /* DeepLinkStrategyFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 993F5506237C622700545511 /* DeepLinkStrategyFactory.swift */; };
9941DFB724E6A52700CDE458 /* ABTestBookingBackButtonColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9941DFB624E6A52700CDE458 /* ABTestBookingBackButtonColor.swift */; };
99425AF4236855BB00D005C0 /* PromoDiscoveryRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99425AF3236855BB00D005C0 /* PromoDiscoveryRouter.swift */; };
99425AFC23685F1E00D005C0 /* PromoDiscoveryPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99425AFB23685F1E00D005C0 /* PromoDiscoveryPresenter.swift */; };
9948ADB424E14517003A826A /* PartnerBannerBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9948ADB324E14517003A826A /* PartnerBannerBuilder.swift */; };
@ -1653,8 +1654,8 @@
990F33B524BC915200D0F426 /* SearchActionBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchActionBarView.swift; sourceTree = "<group>"; };
9917D17C2396793A00A7E06E /* PaidRoutesSubscriptionCampaign.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaidRoutesSubscriptionCampaign.swift; sourceTree = "<group>"; };
9917D17E2397B1D600A7E06E /* IPadModalPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPadModalPresentationController.swift; sourceTree = "<group>"; };
991CE2BA2371D349009EB02A /* PromoCampaignManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromoCampaignManager.swift; sourceTree = "<group>"; };
991CE2BB2371D349009EB02A /* PromoCampaign.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromoCampaign.swift; sourceTree = "<group>"; };
991CE2BA2371D349009EB02A /* ABTestManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ABTestManager.swift; sourceTree = "<group>"; };
991CE2BB2371D349009EB02A /* IABTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IABTest.swift; sourceTree = "<group>"; };
991CE2BE2371D349009EB02A /* PromoDiscoveryCampaign.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PromoDiscoveryCampaign.swift; sourceTree = "<group>"; };
991CE2DC2373145C009EB02A /* PromoAfterBookingCampaign.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromoAfterBookingCampaign.swift; sourceTree = "<group>"; };
991FCA1F23B0FF33009AD684 /* AdsStyleSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsStyleSheet.swift; sourceTree = "<group>"; };
@ -1724,6 +1725,7 @@
993F5504237C622700545511 /* DeepLinkFileStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeepLinkFileStrategy.swift; sourceTree = "<group>"; };
993F5505237C622700545511 /* DeepLinkHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeepLinkHandler.swift; sourceTree = "<group>"; };
993F5506237C622700545511 /* DeepLinkStrategyFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeepLinkStrategyFactory.swift; sourceTree = "<group>"; };
9941DFB624E6A52700CDE458 /* ABTestBookingBackButtonColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ABTestBookingBackButtonColor.swift; sourceTree = "<group>"; };
99425AF3236855BB00D005C0 /* PromoDiscoveryRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromoDiscoveryRouter.swift; sourceTree = "<group>"; };
99425AFB23685F1E00D005C0 /* PromoDiscoveryPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromoDiscoveryPresenter.swift; sourceTree = "<group>"; };
9948ADB324E14517003A826A /* PartnerBannerBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartnerBannerBuilder.swift; sourceTree = "<group>"; };
@ -2565,9 +2567,10 @@
340475281E081A4600C92850 /* Core */ = {
isa = PBXGroup;
children = (
9941DFB024E6A45300CDE458 /* ABTests */,
994AEBE323AB763C0079B81F /* Theme */,
993F54F6237C622700545511 /* DeepLink */,
991CE2B92371D349009EB02A /* PromoCampaign */,
991CE2B92371D349009EB02A /* ABTests */,
CDCA27822245090900167D87 /* EventListening */,
47B9064821C7FA100079C85E /* WebImage */,
470F5A7B2189BA7200754295 /* InappPurchase */,
@ -3650,40 +3653,15 @@
path = TabBar;
sourceTree = "<group>";
};
9917D17B2396790D00A7E06E /* PaidRoutesSubscriptionCampaign */ = {
991CE2B92371D349009EB02A /* ABTests */ = {
isa = PBXGroup;
children = (
9917D17C2396793A00A7E06E /* PaidRoutesSubscriptionCampaign.swift */,
9941DFBB24E6C75600CDE458 /* Tests */,
9941DFBA24E6C74000CDE458 /* Promo */,
991CE2BA2371D349009EB02A /* ABTestManager.swift */,
991CE2BB2371D349009EB02A /* IABTest.swift */,
);
path = PaidRoutesSubscriptionCampaign;
sourceTree = "<group>";
};
991CE2B92371D349009EB02A /* PromoCampaign */ = {
isa = PBXGroup;
children = (
9917D17B2396790D00A7E06E /* PaidRoutesSubscriptionCampaign */,
991CE2DB23731440009EB02A /* PromoAfterBookingCampaign */,
991CE2BD2371D349009EB02A /* PromoDiscoveryCampaign */,
991CE2BA2371D349009EB02A /* PromoCampaignManager.swift */,
991CE2BB2371D349009EB02A /* PromoCampaign.swift */,
);
path = PromoCampaign;
sourceTree = "<group>";
};
991CE2BD2371D349009EB02A /* PromoDiscoveryCampaign */ = {
isa = PBXGroup;
children = (
991CE2BE2371D349009EB02A /* PromoDiscoveryCampaign.swift */,
);
path = PromoDiscoveryCampaign;
sourceTree = "<group>";
};
991CE2DB23731440009EB02A /* PromoAfterBookingCampaign */ = {
isa = PBXGroup;
children = (
991CE2DC2373145C009EB02A /* PromoAfterBookingCampaign.swift */,
);
path = PromoAfterBookingCampaign;
path = ABTests;
sourceTree = "<group>";
};
993DF0C223F6BD0600AC231A /* ElevationDetails */ = {
@ -3817,6 +3795,39 @@
path = Strategies;
sourceTree = "<group>";
};
9941DFB024E6A45300CDE458 /* ABTests */ = {
isa = PBXGroup;
children = (
9941DFB524E6A50E00CDE458 /* Tests */,
);
path = ABTests;
sourceTree = "<group>";
};
9941DFB524E6A50E00CDE458 /* Tests */ = {
isa = PBXGroup;
children = (
);
path = Tests;
sourceTree = "<group>";
};
9941DFBA24E6C74000CDE458 /* Promo */ = {
isa = PBXGroup;
children = (
9917D17C2396793A00A7E06E /* PaidRoutesSubscriptionCampaign.swift */,
991CE2DC2373145C009EB02A /* PromoAfterBookingCampaign.swift */,
991CE2BE2371D349009EB02A /* PromoDiscoveryCampaign.swift */,
);
path = Promo;
sourceTree = "<group>";
};
9941DFBB24E6C75600CDE458 /* Tests */ = {
isa = PBXGroup;
children = (
9941DFB624E6A52700CDE458 /* ABTestBookingBackButtonColor.swift */,
);
path = Tests;
sourceTree = "<group>";
};
994AEBE323AB763C0079B81F /* Theme */ = {
isa = PBXGroup;
children = (
@ -5662,7 +5673,7 @@
F6E2FF451E097BA00083EBEC /* SettingsTableViewLinkCell.swift in Sources */,
34C9BD0A1C6DBCDA000DC38D /* MWMNavigationController.m in Sources */,
CDB92CF822A5350500EC757C /* MWMDiscoveryHotelViewModel.m in Sources */,
991CE2C02371D349009EB02A /* PromoCampaign.swift in Sources */,
991CE2C02371D349009EB02A /* IABTest.swift in Sources */,
F6E2FE311E097BA00083EBEC /* MWMStreetEditorViewController.mm in Sources */,
99CB34B32369DF2E001D28AD /* WhatsNewBuilder.swift in Sources */,
F6E2FE281E097BA00083EBEC /* MWMOpeningHoursSection.mm in Sources */,
@ -5702,7 +5713,7 @@
477D7AC7218F1515007EE2CB /* IPaidRoutePurchase.swift in Sources */,
34E776141F14B17F003040B3 /* AvailableArea.swift in Sources */,
34AB66081FC5AA320078E451 /* MWMNavigationDashboardManager.mm in Sources */,
991CE2BF2371D349009EB02A /* PromoCampaignManager.swift in Sources */,
991CE2BF2371D349009EB02A /* ABTestManager.swift in Sources */,
470F5A5B2181DE7500754295 /* PaidRouteViewController.swift in Sources */,
3486B50D1E27A6DA0069C126 /* MWMPushNotifications.mm in Sources */,
3404F490202898CC0090E401 /* BMCModels.swift in Sources */,
@ -5980,6 +5991,7 @@
991FCA2423B11E61009AD684 /* BookmarksStyleSheet.swift in Sources */,
993DF12823F6BDB100AC231A /* IStyleSheet.swift in Sources */,
99A906E423F6F7030005872B /* CatalogSingleItemViewController.swift in Sources */,
9941DFB724E6A52700CDE458 /* ABTestBookingBackButtonColor.swift in Sources */,
6741AA1C1BF340DE002C974C /* MWMRoutingDisclaimerAlert.m in Sources */,
34D3B0481E389D05004100F9 /* MWMNoteCell.m in Sources */,
CD9AD967228067F500EC174A /* MapInfo.swift in Sources */,