Skip to content

Allow set different widget layout for landscape portrait - #5693

Open
Vladyslav-lys wants to merge 47 commits into
masterfrom
allow_set_different_widget_layout_for_landscape_portrait
Open

Allow set different widget layout for landscape portrait#5693
Vladyslav-lys wants to merge 47 commits into
masterfrom
allow_set_different_widget_layout_for_landscape_portrait

Conversation

@Vladyslav-lys

Copy link
Copy Markdown
Contributor

No description provided.

Vladyslav-lys and others added 27 commits July 13, 2026 16:30
@Vladyslav-lys
Vladyslav-lys requested a review from tigrim August 25, 2026 13:18
@Vladyslav-lys Vladyslav-lys linked an issue Aug 25, 2026 that may be closed by this pull request
80 tasks
@tigrim

tigrim commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Code review notes (build was not run, per request):

  • The new Panels layout setting is saved but does not appear to be applied on the map. PanelsLayoutViewController writes the preference, but the runtime layout still assigns the top/bottom widget widths directly in OAMapInfoController.mm using isLandscapeIpadAware / kInfoViewLandscapeWidthPad / DeviceScreenWidth, and I do not see panelsLayoutMode read from the map layout path. As a result, selecting Wide/Compact in the UI looks successful but should not change the actual widget layout.

  • Independent portrait/landscape mode does not currently separate widget sets/order. The new per-orientation preferences only cover panelsLayoutMode; widget order still goes through the existing shared left/right/top/bottomWidgetPanelOrder preferences via WidgetsPanel.getOrderPreference(). This means editing widgets in Landscape will update the same storage used by Portrait, so the Independent mode does not provide different widget layouts.

  • Copy from Portrait/Landscape layout is exposed in the widgets menu when separate layouts are enabled, but the handler is still a TODO/no-op in WidgetsListViewController.copyWidgets(from:). Users can tap the action and nothing happens.

Vladyslav-lys and others added 2 commits September 3, 2026 19:52
#5694)

* updated widget list, tranparent widgets, panels layout, widgets on map, refactored

* updated shared landscape, updated panels layout changing

* updated copy from another profile, reset to defaults, copy from portrait/landscape

* refactored

* segmented control font scaling

* refactored

* refactored

* isEnabledForAppMode refactored

* copy and reset refactored

* updated to set prefix refactored

* widgetsForPanel refactored

* widgetsForPanel refactored

* widgetsForPanel refactored

* applyStoredLayoutData refactored

* Update WidgetsSettingsHelper.swift

* Update WidgetUtils.swift

* WidgetUtils and WidgetsListViewController refactored

* ScreenElementsMode using updated

* Update ConfigureScreenViewController.swift

* copy from another profile and reset to default updated

* widgets deep link updated

* ipad bottom widget updated

* caching created widgets
@Vladyslav-lys
Vladyslav-lys marked this pull request as ready for review September 4, 2026 08:27

@alex-dev-neo alex-dev-neo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review of this branch (15 findings: 10 correctness, 3 efficiency, 1 altitude, 1 simplification). Inline comments below; each has a collapsed failure scenario.

The two I'd look at before merge:

  1. Switching Screen elements Shared → Independent discards the current widget layout (ScreenElementsViewController.swift:154) — nothing seeds the per-orientation preferences from the shared ones, so on a fresh install the user's whole widget configuration reverts to defaults.
  2. panelsLayoutMode defaults to Wide with no migration (OAAppSettings.m:7142) — every isLandscapeIpadAware check became isCompactPanelsLayout, so existing landscape/iPad users get a visibly different HUD after upgrade.

Findings are suggestions, not blockers — please push back where I've misread the intent.


@objc private func onDonePressed() {
if selectedMode != initialMode {
settings.useSeparateLayouts.set(selectedMode.usesSeparateLayouts, mode: appMode)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness — Switching Screen elements Shared → Independent discards the current widget layout

onDonePressed only flips useSeparateLayouts and calls recreateAllControls(). Nothing seeds the portrait_* / landscape_* preference sets from the shared (base) preferences, so the whole widget configuration is lost on the switch.

Failure scenario

On a fresh install, migrateIfNeeded(isFirstLaunch: true) marks migrateWidgetLayoutPreferences done without running it, so portrait_map_info_controls, portrait_*_widget_panel_order and portrait_custom_widgets_keys are never written. The user configures widgets (every write goes to the base prefs, since preferenceLayoutMode is nil in shared mode), then picks Independent → Done. WidgetsInitializer now reads the prefixed prefs, which are unset, so both orientations revert to the default widget layout.

For upgraded users it reverts to the snapshot migrateWidgetLayoutPreferences took at upgrade time, discarding everything configured since.

Seeding the target layout prefs from the base ones here (the same copy the migration performs) before flipping the flag would fix it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two corrections after re-checking against Android.

1. My framing was wrong. Android does not copy anything on this switch either — MapScreenLayoutFragment just does settings.USE_SEPARATE_LAYOUTS.set(...) + registerAllControls(...), and its migrateWidgetPanels() / migrateWidgetPanelsPages() match the iOS migration. So the original code matched the reference; copySharedWidgetsIfNeeded is an iOS-only improvement over it. Apologies for calling it an iOS defect.

2. The new fix is still inert for upgraded users. It reuses the migration's !target.isSet(for:) guard, but migrateWidgetLayoutPreferences already populated portrait_* / landscape_* at upgrade time:

  1. Upgrade → portrait_map_info_controls = "widget1;widget2"
  2. User (still Shared) adds widget3 → base mapInfoControls = "widget1;widget2;widget3"
  3. Screen elements → Independent → Done: sourceVisibility.isSet is YES but targetVisibility.isSet is also YES → copy skipped → widget3 disappears

The guard is right in a migration (don't clobber what a newer version wrote) and wrong here (intent is "start from what I have now"). It also makes any repeat Shared→Independent switch a no-op. transparentWidgets is not copied either.

Since this is deliberately beyond Android's behaviour, it's your call whether to finish it or drop it for parity — but half-applied is the one option that surprises users.

The ordering is right, though: copy runs before useSeparateLayouts.set(...), inside performBatchedPreferenceNotifications.

OACommonPanelsLayoutMode *preference = (OACommonPanelsLayoutMode *)[_profilePreferences objectForKey:key];
if (!preference)
{
preference = [OACommonPanelsLayoutMode withKey:key defValue:PanelsLayoutModeWide];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CorrectnesspanelsLayoutMode defaults to Wide for every combination — no migration for landscape / iPad

Every layout × screen-elements combination defaults to PanelsLayoutModeWide, and no migration marks the landscape (or iPad) combination Compact. Since this PR replaces all the isLandscapeIpadAware checks with _settings.isCompactPanelsLayout, the HUD silently changes for every existing landscape/iPad user.

Failure scenario

An existing user upgrades and rotates to landscape (or runs on iPad). isCompactPanelsLayout returns NO because landscape_panels_layout_mode is unset and defaults to Wide. Consequences:

  • OAMapInfoController.layoutWidgets sets topWidgetsViewWidthConstraint / bottomWidgetsViewWidthConstraint to DeviceScreenWidth instead of kInfoViewLandscapeWidthPad
  • updateBottomBarViewBackgroundColor paints an opaque widget background where it used to be clear
  • getHudTopOffset adds the top panel height it previously skipped
  • MapHudLayout switches the top/bottom bars from POS_LEFT to POS_FULL_WIDTH

Net effect: a full-width HUD in landscape where the previous release used the compact one. A migration setting Compact for the landscape combination (matching the old isLandscapeIpadAware behaviour) would preserve the existing look.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against Android, with the exact fix. Android needs no migration because it sets the default dynamically (OsmandSettings.getPanelsLayoutMode):

CommonPreference<PanelsLayoutMode> preference = getLayoutPreference(PANELS_LAYOUT_MODE, layoutMode);
if (!portrait || tablet) {
    preference.setDefaultValue(PanelsLayoutMode.COMPACT);
} else {
    preference.setDefaultValue(PanelsLayoutMode.WIDE);
}

That orientation/tablet-dependent default is precisely what preserves the old isLandscapeIpadAware layout. iOS returns a fixed PanelsLayoutModeWide, which is why the HUD changes for existing landscape/iPad users. Mirroring the Android default removes the need for any migration.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked fc64db8e72 — the fix is right in substance, but one clause of the replaced behaviour got dropped.

PanelsLayoutMode defaultValue = screenLayoutMode == ScreenLayoutModeLandscape || [OAUtilities isIPad]

versus what it replaces:

+ (BOOL) isLandscapeIpadAware
{
    return (self.class.isLandscape || self.class.isIPad) && !self.class.isWindowed;
}

!isWindowed is gone. OAUtilities.isWindowed is true for a non-Mac iPad whose window doesn't fill the screen, i.e. Split View / Slide Over — and there the old code returned NO, so the HUD used the Wide layout. Now those windows get Compact, across all 13 sites that read isCompactPanelsLayout: layoutWidgets clamps the top/bottom panels to kInfoViewLandscapeWidthPad, updateBottomBarViewBackgroundColor clears the bar background, and MapHudLayout switches the bars to POS_LEFT — inside an already-narrow window.

There's also a structural limit worth deciding on. The default is computed once, when the preference is created in registerWidgetLayoutPreferences during OAAppSettings init. Orientation survives that because it's encoded in the key (single_portrait_… vs single_landscape_…), but the windowed state isn't in the key, so a frozen default can't track the user dragging the Split View divider.

Android sidesteps this by re-applying the default on every read rather than at creation:

public CommonPreference<PanelsLayoutMode> getPanelsLayoutMode(@NonNull @UiContext Context context, @Nullable ScreenLayoutMode layoutMode) {
    boolean tablet = AndroidUiHelper.isTablet(context);
    boolean portrait = AndroidUiHelper.isOrientationPortrait(context);

    CommonPreference<PanelsLayoutMode> preference = getLayoutPreference(PANELS_LAYOUT_MODE, layoutMode);
    if (!portrait || tablet) {
        preference.setDefaultValue(PanelsLayoutMode.COMPACT);
    } else {
        preference.setDefaultValue(PanelsLayoutMode.WIDE);
    }
    return preference;
}

The same shape works here — move the assignment out of the if (!preference) block so it runs on every call, and add the missing clause:

preference.defValue = (screenLayoutMode == ScreenLayoutModeLandscape || [OAUtilities isIPad])
        && ![OAUtilities isWindowed]
    ? PanelsLayoutModeCompact
    : PanelsLayoutModeWide;

If you'd rather keep it at creation time, adding just && ![OAUtilities isWindowed] still fixes the regression for the common case — it only leaves the divider-drag case behind.


@objc(OAWidgetRegistrationDelegate)
protocol WidgetRegistrationDelegate {
var screenLayoutMode: ScreenLayoutMode { get }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness — Plugin widgets resolve panel/page/order from the wrong preference set

WidgetRegistrationDelegate exposes only screenLayoutMode, so every plugin's createWidgets: builds WidgetInfoCreator(appMode:screenLayoutMode:) — the convenience init, which re-derives preferenceLayoutMode from useSeparateLayouts instead of using the explicit preferenceLayoutMode the enclosing WidgetsInitializer was constructed with.

Failure scenario

A profile has useSeparateLayouts == true. WidgetsSettingsHelper.allPreferenceLayoutModes (and OAMapWidgetRegistry.widgetsForAppMode:layoutMode: with layoutMode == nil) call createAllControls(appMode:screenLayoutMode: .portrait, preferenceLayoutMode: nil).

Core widgets then read page/order/panel from the base prefs, but OAWeatherPlugin, OAMonitoringPlugin, OAParkingPositionPlugin, VehicleMetricsPlugin, OAExternalSensorsPlugin, OAMapillaryPlugin and OAOsmandDevelopmentPlugin re-derive preferenceLayoutMode as portrait and read portrait_left_widget_panel_order instead.

So within a single widget set, plugin widgets land on different panels/pages than core widgets, and the nil pass of copyConfigureScreenSettings copies a mixed configuration. Adding preferenceLayoutMode to the delegate protocol (and passing it through to the plugins' WidgetInfoCreator) would keep one source of truth.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against Android — it threads the nullable layout mode all the way through:

// WidgetsInitializer.createAllControls
PluginsHelper.createMapWidgets(mapActivity, mapWidgetsCache, appMode, layoutMode);

// WeatherPlugin.createWidgets(..., @Nullable ScreenLayoutMode layoutMode)
WidgetInfoCreator creator = new WidgetInfoCreator(app, appMode, layoutMode);

Android models this as one @Nullable ScreenLayoutMode; iOS split it into a non-optional screenLayoutMode plus a nullable preferenceLayoutMode, and the delegate carries only the former — that's where the nullability is lost. Adding preferenceLayoutMode to WidgetRegistrationDelegate and passing it into the plugins' WidgetInfoCreator restores parity.

panel: WidgetsPanel,
widgetParams: [String: Any]? = nil) {
OAAppSettings.performBatchedPreferenceNotifications { [self] in
let sourceLayoutMode = preferenceLayoutMode != nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness — Copy-from-profile picks the source layout from the target profile's setting

sourceLayoutMode is derived from preferenceLayoutMode, which reflects the target app mode's useSeparateLayouts. The source profile's own setting is never consulted.

Failure scenario

Target profile Car has Independent layouts; source profile Bicycle has Shared layouts, so all of Bicycle's widgets live in the base prefs and its portrait_* prefs are unset.

User opens the widget list for Car → "Copy from other profile" → Bicycle. preferenceLayoutMode is non-nil, so sourceLayoutMode becomes portrait and widgetRegistry.widgets(forPanel: bicycle, layoutMode: portrait) reads Bicycle's never-written portrait_* prefs. The copy silently produces the default widget set instead of Bicycle's actual configuration.

The source layout should be resolved from settings.useSeparateLayouts.get(fromAppMode).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Withdrawing this comment — I was wrong.

I re-checked against the Android implementation and it does the same thing, so this is the reference behaviour, not an iOS defect.

ConfigureWidgetsFragment.copyAppModePrefs calls copyPreferences(appMode, layoutMode) where layoutMode is the fragment's own (target-side) ScreenLayoutMode.getDefault(...), and WidgetsSettingsHelper.copyWidgetsForPanel passes it straight into getWidgetsForPanel(mapActivity, fromAppMode, fromLayoutMode, ...). So on Android, copying from a Shared profile into an Independent one also reads the source's portrait_* prefs.

The underlying UX question is real but shared with upstream — it belongs there, not as a change on iOS alone. Sorry for the noise.

panels: WidgetsPanel.values,
layoutMode: preferenceLayoutMode) {
for widgetInfo in allWidgetInfos {
widgetRegistry.enableDisableWidget(for: appMode,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness — Reset loop writes back into preferences it already reset

This calls widgetRegistry.enableDisableWidget directly instead of the layout-aware enableDisableWidget(_:enabled:screenLayoutMode:) helper added further down in this same file, so every iteration writes to the current layout's mapInfoControls regardless of which layout that iteration is resetting.

Failure scenario

Profile with useSeparateLayouts == false, so the current pref is the base one:

  1. iteration nil — disables all widgets into base mapInfoControls, then resetWidgetPreferences(nil) resets it ✅
  2. iteration portraitenableDisableForMode again resolves through useSeparateLayouts == false and writes base mapInfoControls, then resets only portrait_map_info_controls
  3. iteration landscape — same, writes base again ❌

After "Reset to default" the base mapInfoControls is left explicitly written rather than unset, so isSet(for:) now reports true for a preference the user just reset. Routing through the layout-aware helper (as defaultWidgetInfos and createDuplicateWidgetInfo already do) fixes it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against Android, which resets one layout mode rather than looping over three, and passes it explicitly:

public void resetConfigureScreenSettings() {
    Set<MapWidgetInfo> allWidgetInfos = widgetRegistry.getWidgetsForPanel(mapActivity, appMode,
            layoutMode, MATCHING_PANELS_MODE, Arrays.asList(WidgetsPanel.values()));
    for (MapWidgetInfo widgetInfo : allWidgetInfos) {
        widgetRegistry.enableDisableWidgetForMode(appMode, widgetInfo, null, layoutMode, false);
    }
    settings.getMapInfoControls(layoutMode).resetModeToDefault(appMode);
    ...
}

Both halves of the divergence matter: the 3-way loop is an iOS invention, and the call drops the layout mode so every iteration writes the current layout.

[_mapInfoController viewWillTransition:size];
[self resetToDefaultRulerLayout];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
[_mapInfoController recreateControls];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Efficiency — Every rotation recreates all widget views

This runs unconditionally in the transition completion, and recreateControls calls [_mapWidgetRegistry registerAllControls], rebuilding every MapWidgetInfo and widget UIView. But the layout can only differ between orientations when useSeparateLayouts is on.

Failure scenario

A user with the default Shared screen elements rotates the device. registerAllControls clears _createdWidgetsCache, calls WidgetsInitializer.createAllControls (~40 widget views plus every plugin's widgets), reorders them and re-attaches them to the panels — all on the main thread inside the rotation completion, to produce exactly the same widget set.

Gating on settings.useSeparateLayouts.get(appMode) (or on the resolved ScreenLayoutMode actually changing) keeps the shared case on its existing widget instances.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Withdrawing this comment — and please ignore the fix I suggested, it would be harmful.

AndroidManifest.xml declares android:configChanges="uiMode" for MapActivity — orientation is not listed, so Android destroys and recreates the whole Activity on rotation, rebuilding MapHudLayout, MapInfoLayer and every widget. Recreating controls here is strictly cheaper than the reference.

More importantly, my suggestion to gate this on useSeparateLayouts would break the correct fix for the panels-layout default: on Android that default depends on !portrait || tablet, so the effective layout changes on rotation even in Shared mode. The rebuild has to stay unconditional.

appModeCache = [NSMutableDictionary dictionary];
_createdWidgetsCache[appMode.stringKey] = appModeCache;
}
appModeCache[layoutModeKey] = createdWidgets;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Efficiency_createdWidgetsCache holds full widget sets indefinitely and goes stale

Entries are keyed by appMode.stringKey × layout key and only ever emptied by clearWidgets / registerAllControls. Nothing bounds the dictionary, and nothing invalidates an entry when that layout's preferences change.

Failure scenario

Memory: switching the Portrait/Landscape segment in Configure Screen, or running copyConfigureScreenSettings (which iterates [nil, portrait, landscape]) across several profiles, materialises a separate full widget set per (appMode, layout) pair — each ~40 UIView widgets holding OsmAndApp / settings references and update blocks — all kept alive until the next registerAllControls.

Staleness: a MapWidgetInfo's pageIndex / priority are computed at creation, so editing the non-displayed layout's order and re-reading it through pagedWidgetsForPanel:...screenLayoutMode: returns the pre-edit order unless a full recreate happens to intervene.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against Android, which keeps no cache at all:

public List<MapWidgetInfo> getWidgets(@NonNull MapActivity activity, @NonNull ApplicationMode appMode, @Nullable ScreenLayoutMode layoutMode) {
    List<MapWidgetInfo> list = new ArrayList<>();
    if (settings.getApplicationMode() == appMode && (layoutMode == null || ScreenLayoutMode.getDefault(activity) == layoutMode)) {
        list.addAll(getAllWidgets());
    } else {
        list.addAll(WidgetsInitializer.createAllControls(activity, appMode, layoutMode));
    }
    return list;
}

Live set when it matches the current mode, throwaway list otherwise — which is what avoids both the unbounded retention and the staleness.

if (_isLayingOutWidgets)
return;

_isLayingOutWidgets = YES;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Altitude — Re-entrancy flag silently drops nested layout passes

_isLayingOutWidgets makes any nested layoutWidgets invocation a no-op, rather than addressing why the method now recurses.

Failure scenario

layoutWidgets ends by calling [self.delegate widgetsLayoutDidChange:YES] and [_mapWidgetRegistry notifyWidgetsPanelsDidLayout], and the new compact-portrait branch reads widgetsView.bounds / calculateContentSize, whose results change as those notifications drive further layout.

When an observer synchronously asks for another pass — exactly the case where the panel widths just computed are now out of date — the flag swallows it, and the HUD keeps the stale constants until some unrelated event triggers a new pass.

The cause is the layout→notify→layout cycle introduced here. Breaking it (computing the panel widths before notifying, or coalescing the pass onto the next runloop) removes the need for the flag.

return settings.bottomWidgetPanelOrder
}
fatalError("Unsupported panel")
func orderPreference(screenLayoutMode: NSNumber?, appMode: OAApplicationMode) -> OACommonListOfStringList {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SimplificationorderPreference ignores its appMode parameter

appMode is never used — the body forwards only self and screenLayoutMode to settings.widgetPanelOrder(_:screenLayoutMode:).

Failure scenario

Seven call sites (WidgetType.findWidgetPanel, WidgetsPanel.reorderedPages, setWidgetsOrder, WidgetsSettingsHelper.defaultWidgetInfos, resetWidgetsForPanel, …) compute and thread an argument that has no effect. It reads as if the preference were app-mode-scoped, inviting a caller to pass a different app mode expecting different preferences. Either drop the parameter or make widgetPanelOrder actually take it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against Android — the signature has no app mode, because the preference isn't app-mode-scoped:

public ListStringPreference getOrderPreference(@NonNull OsmandSettings settings, @Nullable ScreenLayoutMode layoutMode)

Comment thread Sources/Helpers/MigrationManager.swift Outdated
}

for panel in WidgetsPanel.values {
let sourceOrder = settings.widgetPanelOrder(panel, screenLayoutMode: nil)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Efficiency — Source preferences re-resolved inside the nested loops

settings.widgetPanelOrder(panel, screenLayoutMode: nil) (and mapInfoControls(nil) / customWidgetKeys(nil) above) do not depend on any loop variable, but are re-resolved on every iteration.

Failure scenario

For every app mode (OAApplicationMode.allPossibleValues()) × 2 layouts × 4 panels this re-enters layoutPreference:, which takes @synchronized(_profilePreferences) and does a map lookup — 8 redundant locked lookups per app mode for the panel orders alone, plus 2 more for visibility/custom keys, all resolving to the same base preference objects. Hoisting the three source lookups above the loops is equivalent and cheaper.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed against Android, which hoists the source preferences above the app-mode loop:

private void migrateWidgetPanels() {
    CommonPreference<String> originalMapControls = settings.getMapInfoControls(null);
    ListStringPreference originalCustomWidgetsKeys = settings.getCustomWidgetsKeys(null);
    CommonPreference<Boolean> originalTransparentPreference = settings.getTransparentMapThemePreference(null);

    for (ApplicationMode appMode : ApplicationMode.allPossibleValues()) { ... }
}

let disabled = !defaultWidgetInfo.isEnabledForAppMode(appMode,
widgetsVisibility: widgetsVisibility)
let inAnotherPanel = defaultWidgetInfo.widgetPanel != panel
if duplicateNotPossible || (disabled && !inAnotherPanel) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness — missing defaultAlreadyUsed guard lets the same default widget id be added twice

Found while re-checking this PR against the Android implementation. Android guards default-widget reuse:

boolean defaultAlreadyUsed = newPagedOrder.stream()
        .anyMatch(page -> page.contains(defaultWidgetInfo.key));
boolean canReuseDefault = (duplicateNotPossible || (disabled && !inAnotherPanel)) && !defaultAlreadyUsed;

if (canReuseDefault) {
    widgetRegistry.enableDisableWidgetForMode(appMode, defaultWidgetInfo, true, layoutMode, false);
    widgetIdToAdd = defaultWidgetInfo.key;
} else if (widgetTypeToCopy != null) {
    ...
}

widgetsVisibility is snapshotted once before the loop (line 156), so disabled never reflects a widget enabled during the loop — which is exactly why Android needs the extra guard. This port kept the snapshot but dropped the guard.

Failure scenario

Copy a panel whose source holds both speed and its duplicate speed__abc, with speed disabled in the target profile:

  1. iteration for speeddisabled && !inAnotherPanel → reuse, append speed to newPagedOrder, enable it
  2. iteration for speed__abcdisabled is still true from the stale snapshot → reuse speed againspeed appears twice in the panel order

⚠️ When fixing, mirror Android's else if (widgetTypeToCopy != nil) too. Today the else branch force-unwraps widgetTypeToCopy!, which is only safe because duplicateNotPossible short-circuits into the if. Adding && !defaultAlreadyUsed makes that branch reachable with a nil type and it would crash.

@alex-dev-neo

Copy link
Copy Markdown
Contributor

Re-reviewed my earlier comments against the Android implementation (OsmAnd master, 8106d0c281), since this feature already exists there and is the reference.

Withdrawn — 3 comments, I was wrong:

Comment Why
Copy-from-profile picks source layout from target's setting Android's ConfigureWidgetsFragment passes the target-side layoutMode the same way
mapInfoControls trailing separator Android writes the trailing separator too; Java's split drops trailing empties, and this port compensates with .filter
Every rotation recreates all widget views Android recreates the whole Activity on rotation (configChanges omits orientation), and my suggested gating would break the panels-layout default fix

Corrected — 1 comment: the Screen elements Shared→Independent one. Android doesn't copy on that switch either, so the original code matched the reference and my "iOS defect" framing was wrong — but the new copySharedWidgetsIfNeeded is inert for upgraded users because of the !isSet guard, so it's currently half-applied.

Added — 1 comment: missing defaultAlreadyUsed guard in copyWidgetsForPanel, which lets the same default widget id land in the panel order twice.

Confirmed with Android references — 8 comments, each now quoting the corresponding upstream code so the shape of the fix is explicit. The highest-value one is the panels-layout default: Android sets it dynamically to COMPACT when !portrait || tablet, which is exactly what preserves the old isLandscapeIpadAware layout and removes the need for a migration.

Apologies for the three false positives — thanks for bearing with the correction pass.

@@ -20,20 +20,38 @@ protocol MapButtonsDelegate: AnyObject {

@objc(OAConfigureScreenViewController)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove OA


@objc(OAConfigureScreenViewController)
@objcMembers
class ConfigureScreenViewController: OABaseNavbarViewController, AppModeSelectionDelegate, WidgetStateDelegate, MapButtonsDelegate {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the superclass changed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because OABaseNavbarSubviewViewController allows to insert segmented control to the needed place

row.title = panel.title
row.iconName = panel.iconName(for: screenLayoutMode)
row.setObj(panel, forKey: "panel")
row.iconTintColor = widgetsCount == 0 ? .iconColorDefault : appMode!.getProfileColor()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

force unwrap


let transparencyRow = widgetsSection.createNewRow()
transparencyRow.title = localizedString("map_widget_transparent")
transparencyRow.key = "map_widget_transparent"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key to enum

import UIKit

final class DoubleImageHeaderCell: UITableViewCell {
@IBOutlet weak var leftBackgroundImageView: UIImageView!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private

@@ -229,6 +229,8 @@
274781F62DB92E3800EAE008 /* ColorsAppearanceCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274781F52DB92E3100EAE008 /* ColorsAppearanceCategory.swift */; };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb2c5f1b0 UIView:0xcca3c9dc0.width == 30 (active)>",
"<NSLayoutConstraint:0xcb2c5ec10 H:|-(16)-[UIStackView:0xcca3c9500] (active, names: '|':OsmAnd_Maps.SensorTextWidget:0xcb2c25c00 )>",
"<NSLayoutConstraint:0xcb2c5ec60 UIStackView:0xcca3c9500.trailing == OsmAnd_Maps.SensorTextWidget:0xcb2c25c00.trailing - 16 (active)>",
"<NSLayoutConstraint:0xcb2c5e940 UIView:0xcca3c8c40.width == UIStackView:0xcca3c8a80.width (active)>",
"<NSLayoutConstraint:0xcb2cec140 H:|-(0)-[UIStackView:0xcca3c8a80] (active, names: '|':UIView:0xcca3c8380 )>",
"<NSLayoutConstraint:0xcb2cec190 UIStackView:0xcca3c8a80.trailing == UIView:0xcca3c8380.trailing (active)>",
"<NSLayoutConstraint:0xcb2d1a990 'UISV-alignment' OADestinationBarWidget:0xcca205180.leading == UIStackView:0xcca3c8fc0.leading (active)>",
"<NSLayoutConstraint:0xcb2c5ff70 'UISV-alignment' OADestinationBarWidget:0xcca205180.leading == UIView:0xcca3c8c40.leading (active)>",
"<NSLayoutConstraint:0xcb2ca0000 'UISV-alignment' OADestinationBarWidget:0xcca205180.trailing == UIView:0xcca3c8c40.trailing (active)>",
"<NSLayoutConstraint:0xcb2ced130 'UISV-alignment' UIStackView:0xcca3c96c0.leading == UIStackView:0xcca3c9c00.leading (active)>",
"<NSLayoutConstraint:0xcb2ced180 'UISV-alignment' UIStackView:0xcca3c96c0.trailing == UIStackView:0xcca3c9c00.trailing (active)>",
"<NSLayoutConstraint:0xcb2d1aad0 'UISV-alignment' OADestinationBarWidget:0xcca205180.trailing == UIStackView:0xcca3c8fc0.trailing (active)>",
"<NSLayoutConstraint:0xcb2cecb40 'UISV-canvas-connection' UIStackView:0xcca3c9c00.leading == UIView:0xcca3c9dc0.leading (active)>",
"<NSLayoutConstraint:0xcb2cecb90 'UISV-canvas-connection' H:[UIView:0xcca3c9f80]-(0)-| (active, names: '|':UIStackView:0xcca3c9c00 )>",
"<NSLayoutConstraint:0xcb2ced090 'UISV-canvas-connection' UIStackView:0xcca3c9500.leading == UIStackView:0xcca3c96c0.leading (active)>",
"<NSLayoutConstraint:0xcb2ced0e0 'UISV-canvas-connection' H:[UIStackView:0xcca3c96c0]-(0)-| (active, names: '|':UIStackView:0xcca3c9500 )>",
"<NSLayoutConstraint:0xcb2ceec10 'UISV-canvas-connection' UIStackView:0xcca3c8fc0.leading == OsmAnd_Maps.SensorTextWidget:0xcb2c25c00.leading (active)>",
"<NSLayoutConstraint:0xcb2ceec60 'UISV-canvas-connection' H:[OsmAnd_Maps.RulerDistanceWidget:0xcb2c47100]-(0)-| (active, names: '|':UIStackView:0xcca3c8fc0 )>",
"<NSLayoutConstraint:0xcb2ceed00 'UISV-fill-equally' OsmAnd_Maps.CurrentTimeWidget:0xcb2c46a00.width == OsmAnd_Maps.SensorTextWidget:0xcb2c25c00.width (active)>",
"<NSLayoutConstraint:0xcb2ceeda0 'UISV-fill-equally' OsmAnd_Maps.RulerDistanceWidget:0xcb2c47100.width == OsmAnd_Maps.SensorTextWidget:0xcb2c25c00.width (active)>",
"<NSLayoutConstraint:0xcb2cecbe0 'UISV-spacing' H:[UIView:0xcca3c9dc0]-(12)-[UIView:0xcca3c9f80] (active)>",
"<NSLayoutConstraint:0xcb2ceecb0 'UISV-spacing' H:[OsmAnd_Maps.SensorTextWidget:0xcb2c25c00]-(0)-[OsmAnd_Maps.CurrentTimeWidget:0xcb2c46a00] (active)>",
"<NSLayoutConstraint:0xcb2ceed50 'UISV-spacing' H:[OsmAnd_Maps.CurrentTimeWidget:0xcb2c46a00]-(0)-[OsmAnd_Maps.RulerDistanceWidget:0xcb2c47100] (active)>",
"<NSLayoutConstraint:0xcb2d1af30 'UIView-Encapsulated-Layout-Width' UIView:0xcca3c8380.width == 97.5 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb2c5f1b0 UIView:0xcca3c9dc0.width == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

274781F62DB92E3800EAE008 /* ColorsAppearanceCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274781F52DB92E3100EAE008 /* ColorsAppearanceCategory.swift */; };
274C43F12DEDBA7100585952 /* OANextTurnWidget.xib in Resources */ = {isa = PBXBuildFile; fileRef = 274C43F02DEDBA7100585952 /* OANextTurnWidget.xib */; };
2753876E2ECDD0AD000CF0F3 /* VehicleAlgorithms.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2753876D2ECDD0AD000CF0F3 /* VehicleAlgorithms.swift */; };
27584BF6302DE44B009AC53F /* DoubleImageHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27584BF4302DE44B009AC53F /* DoubleImageHeaderCell.swift */; };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error retrieving battery status: result= 18 446 744 073 172 681 409 percent= 1 hasExternalConnected= 0 isCharging= 144 isFullyCharged= 149
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb3768550 UIView:0xcca3f2840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37685a0 UIView:0xcca3f2a00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37685f0 UIView:0xcca3f1f80.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768870 UILabel:0xcb36bce00.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb3768b40 UIView:0xcca3f01c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768b90 UIView:0xcca3f0380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768be0 UIView:0xcca3f0000.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768dc0 V:[UIStackView:0xcca3f2680]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3f24c0 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb3768550 UIView:0xcca3f2840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37685a0 UIView:0xcca3f2a00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768a50 UILabel:0xcb36bd880.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37689b0 UIView:0xcca3f0c40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768af0 UIView:0xcca3f08c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768b90 UIView:0xcca3f0380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768be0 UIView:0xcca3f0000.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768dc0 V:[UIStackView:0xcca3f2680]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3f24c0 )>",
"<NSLayoutConstraint:0xcb3768e10 V:|-(0)-[UIStackView:0xcca3f2680] (active, names: '|':UITableViewCellContentView:0xcca3f24c0 )>",
"<NSLayoutConstraint:0xcb376a440 'UISV-alignment' UIButton:0xcca3a8f00.centerY == UIStackView:0xcca3f0a80.centerY (active)>",
"<NSLayoutConstraint:0xcb3769220 'UISV-canvas-connection' UIStackView:0xcca3f2bc0.top == UIView:0xcca3f2840.top (active)>",
"<NSLayoutConstraint:0xcb3769270 'UISV-canvas-connection' V:[UIView:0xcca3f2a00]-(0)-| (active, names: '|':UIStackView:0xcca3f2bc0 )>",
"<NSLayoutConstraint:0xcb37698b0 'UISV-canvas-connection' UIStackView:0xcca3f0a80.top == UIView:0xcca3f0c40.top (active)>",
"<NSLayoutConstraint:0xcb3769900 'UISV-canvas-connection' V:[UIView:0xcca3f08c0]-(0)-| (active, names: '|':UIStackView:0xcca3f0a80 )>",
"<NSLayoutConstraint:0xcb376a1c0 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcafdbfd00'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca3f2140 )>",
"<NSLayoutConstraint:0xcb376a210 'UISV-canvas-connection' UIStackView:0xcca3f2140.centerY == UIButton:0xcca3a8f00.centerY (active)>",
"<NSLayoutConstraint:0xcb376a490 'UISV-canvas-connection' UIStackView:0xcca3f0540.top == UIView:0xcca3f0380.top (active)>",
"<NSLayoutConstraint:0xcb376a4e0 'UISV-canvas-connection' V:[UIView:0xcca3f0000]-(0)-| (active, names: '|':UIStackView:0xcca3f0540 )>",
"<NSLayoutConstraint:0xcb376a6c0 'UISV-canvas-connection' UIStackView:0xcca3f2680.top == UIStackView:0xcca3f2bc0.top (active)>",
"<NSLayoutConstraint:0xcb376a710 'UISV-canvas-connection' V:[UIStackView:0xcca3f0540]-(0)-| (active, names: '|':UIStackView:0xcca3f2680 )>",
"<NSLayoutConstraint:0xcb37692c0 'UISV-spacing' V:[UIView:0xcca3f2840]-(5)-[UIView:0xcca3f2a00] (active)>",
"<NSLayoutConstraint:0xcb3769950 'UISV-spacing' V:[UIView:0xcca3f0c40]-(4)-[UILabel:0xcb36bd880] (active)>",
"<NSLayoutConstraint:0xcb37699a0 'UISV-spacing' V:[UILabel:0xcb36bd880]-(4)-[UIView:0xcca3f08c0] (active)>",
"<NSLayoutConstraint:0xcb376a530 'UISV-spacing' V:[UIView:0xcca3f0380]-(5)-[UIView:0xcca3f0000] (active)>",
"<NSLayoutConstraint:0xcb376b0c0 'UISV-spacing' V:[UIStackView:0xcca3f2bc0]-(4)-[UIStackView:0xcca3f2140] (active)>",
"<NSLayoutConstraint:0xcb376b160 'UISV-spacing' V:[UIStackView:0xcca3f2140]-(4)-[UIStackView:0xcca3f0540] (active)>",
"<NSLayoutConstraint:0xcb376a120 'UISV-spanning-boundary' _UILayoutSpacer:0xcafdbfd00'UISV-alignment-spanner'.bottom >= UIStackView:0xcca3f0a80.bottom (active)>",
"<NSLayoutConstraint:0xcb376ac10 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca3f24c0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb3768a50 UILabel:0xcb36bd880.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb3768550 UIView:0xcca3f2840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37685a0 UIView:0xcca3f2a00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768780 UIImageView:0xcca55aa00.height == 30 (active)>",
"<NSLayoutConstraint:0xcb3768b90 UIView:0xcca3f0380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768be0 UIView:0xcca3f0000.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768dc0 V:[UIStackView:0xcca3f2680]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3f24c0 )>",
"<NSLayoutConstraint:0xcb3768e10 V:|-(0)-[UIStackView:0xcca3f2680] (active, names: '|':UITableViewCellContentView:0xcca3f24c0 )>",
"<NSLayoutConstraint:0xcb376a3a0 'UISV-alignment' UIButton:0xcca3a8f00.centerY == UIImageView:0xcca55aa00.centerY (active)>",
"<NSLayoutConstraint:0xcb3769220 'UISV-canvas-connection' UIStackView:0xcca3f2bc0.top == UIView:0xcca3f2840.top (active)>",
"<NSLayoutConstraint:0xcb3769270 'UISV-canvas-connection' V:[UIView:0xcca3f2a00]-(0)-| (active, names: '|':UIStackView:0xcca3f2bc0 )>",
"<NSLayoutConstraint:0xcb376a170 'UISV-canvas-connection' UIStackView:0xcca3f2140.top == _UILayoutSpacer:0xcafdbfd00'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb376a210 'UISV-canvas-connection' UIStackView:0xcca3f2140.centerY == UIButton:0xcca3a8f00.centerY (active)>",
"<NSLayoutConstraint:0xcb376a490 'UISV-canvas-connection' UIStackView:0xcca3f0540.top == UIView:0xcca3f0380.top (active)>",
"<NSLayoutConstraint:0xcb376a4e0 'UISV-canvas-connection' V:[UIView:0xcca3f0000]-(0)-| (active, names: '|':UIStackView:0xcca3f0540 )>",
"<NSLayoutConstraint:0xcb376a6c0 'UISV-canvas-connection' UIStackView:0xcca3f2680.top == UIStackView:0xcca3f2bc0.top (active)>",
"<NSLayoutConstraint:0xcb376a710 'UISV-canvas-connection' V:[UIStackView:0xcca3f0540]-(0)-| (active, names: '|':UIStackView:0xcca3f2680 )>",
"<NSLayoutConstraint:0xcb37692c0 'UISV-spacing' V:[UIView:0xcca3f2840]-(5)-[UIView:0xcca3f2a00] (active)>",
"<NSLayoutConstraint:0xcb376a530 'UISV-spacing' V:[UIView:0xcca3f0380]-(5)-[UIView:0xcca3f0000] (active)>",
"<NSLayoutConstraint:0xcb376b0c0 'UISV-spacing' V:[UIStackView:0xcca3f2bc0]-(4)-[UIStackView:0xcca3f2140] (active)>",
"<NSLayoutConstraint:0xcb376b160 'UISV-spacing' V:[UIStackView:0xcca3f2140]-(4)-[UIStackView:0xcca3f0540] (active)>",
"<NSLayoutConstraint:0xcb3769f90 'UISV-spanning-boundary' _UILayoutSpacer:0xcafdbfd00'UISV-alignment-spanner'.top <= UIImageView:0xcca55aa00.top (active)>",
"<NSLayoutConstraint:0xcb376ac10 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca3f24c0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb3768780 UIImageView:0xcca55aa00.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37686e0 UIView:0xcca27d180.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768cd0 UIView:0xcca27cfc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3769e50 UIView:0xcca27ce00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376a800 UILabel:0xcb36bdc00.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb376b390 UIView:0xcca27e680.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b570 UIView:0xcca27e300.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b3e0 UIView:0xcca27e140.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b610 V:[UIStackView:0xcca3f16c0]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3f1340 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37686e0 UIView:0xcca27d180.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768cd0 UIView:0xcca27cfc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b340 UILabel:0xcb36be300.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb376b250 UIView:0xcca27d500.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b2f0 UIView:0xcca27e840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b570 UIView:0xcca27e300.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b3e0 UIView:0xcca27e140.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b610 V:[UIStackView:0xcca3f16c0]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3f1340 )>",
"<NSLayoutConstraint:0xcb376b6b0 V:|-(0)-[UIStackView:0xcca3f16c0] (active, names: '|':UITableViewCellContentView:0xcca3f1340 )>",
"<NSLayoutConstraint:0xcb3790d20 'UISV-alignment' UIButton:0xcca3ab300.centerY == UIStackView:0xcca27d6c0.centerY (active)>",
"<NSLayoutConstraint:0xcb376bac0 'UISV-canvas-connection' UIStackView:0xcca27d340.top == UIView:0xcca27d180.top (active)>",
"<NSLayoutConstraint:0xcb376bb10 'UISV-canvas-connection' V:[UIView:0xcca27cfc0]-(0)-| (active, names: '|':UIStackView:0xcca27d340 )>",
"<NSLayoutConstraint:0xcb3790190 'UISV-canvas-connection' UIStackView:0xcca27d6c0.top == UIView:0xcca27d500.top (active)>",
"<NSLayoutConstraint:0xcb37901e0 'UISV-canvas-connection' V:[UIView:0xcca27e840]-(0)-| (active, names: '|':UIStackView:0xcca27d6c0 )>",
"<NSLayoutConstraint:0xcb3790aa0 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcbe843600'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca27ddc0 )>",
"<NSLayoutConstraint:0xcb3790af0 'UISV-canvas-connection' UIStackView:0xcca27ddc0.centerY == UIButton:0xcca3ab300.centerY (active)>",
"<NSLayoutConstraint:0xcb3790d70 'UISV-canvas-connection' UIStackView:0xcca27e4c0.top == UIView:0xcca27e300.top (active)>",
"<NSLayoutConstraint:0xcb3790dc0 'UISV-canvas-connection' V:[UIView:0xcca27e140]-(0)-| (active, names: '|':UIStackView:0xcca27e4c0 )>",
"<NSLayoutConstraint:0xcb3790fa0 'UISV-canvas-connection' UIStackView:0xcca3f16c0.top == UIStackView:0xcca27d340.top (active)>",
"<NSLayoutConstraint:0xcb3790ff0 'UISV-canvas-connection' V:[UIStackView:0xcca27e4c0]-(0)-| (active, names: '|':UIStackView:0xcca3f16c0 )>",
"<NSLayoutConstraint:0xcb376bb60 'UISV-spacing' V:[UIView:0xcca27d180]-(5)-[UIView:0xcca27cfc0] (active)>",
"<NSLayoutConstraint:0xcb3790230 'UISV-spacing' V:[UIView:0xcca27d500]-(4)-[UILabel:0xcb36be300] (active)>",
"<NSLayoutConstraint:0xcb3790280 'UISV-spacing' V:[UILabel:0xcb36be300]-(4)-[UIView:0xcca27e840] (active)>",
"<NSLayoutConstraint:0xcb3790e10 'UISV-spacing' V:[UIView:0xcca27e300]-(5)-[UIView:0xcca27e140] (active)>",
"<NSLayoutConstraint:0xcb3791a40 'UISV-spacing' V:[UIStackView:0xcca27d340]-(4)-[UIStackView:0xcca27ddc0] (active)>",
"<NSLayoutConstraint:0xcb3791b30 'UISV-spacing' V:[UIStackView:0xcca27ddc0]-(4)-[UIStackView:0xcca27e4c0] (active)>",
"<NSLayoutConstraint:0xcb3790a00 'UISV-spanning-boundary' _UILayoutSpacer:0xcbe843600'UISV-alignment-spanner'.bottom >= UIStackView:0xcca27d6c0.bottom (active)>",
"<NSLayoutConstraint:0xcb37914f0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca3f1340.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb376b340 UILabel:0xcb36be300.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37686e0 UIView:0xcca27d180.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3768cd0 UIView:0xcca27cfc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376aee0 UIImageView:0xcca22a400.height == 30 (active)>",
"<NSLayoutConstraint:0xcb376b570 UIView:0xcca27e300.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b3e0 UIView:0xcca27e140.height == 0 (active)>",
"<NSLayoutConstraint:0xcb376b610 V:[UIStackView:0xcca3f16c0]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3f1340 )>",
"<NSLayoutConstraint:0xcb376b6b0 V:|-(0)-[UIStackView:0xcca3f16c0] (active, names: '|':UITableViewCellContentView:0xcca3f1340 )>",
"<NSLayoutConstraint:0xcb3790c80 'UISV-alignment' UIButton:0xcca3ab300.centerY == UIImageView:0xcca22a400.centerY (active)>",
"<NSLayoutConstraint:0xcb376bac0 'UISV-canvas-connection' UIStackView:0xcca27d340.top == UIView:0xcca27d180.top (active)>",
"<NSLayoutConstraint:0xcb376bb10 'UISV-canvas-connection' V:[UIView:0xcca27cfc0]-(0)-| (active, names: '|':UIStackView:0xcca27d340 )>",
"<NSLayoutConstraint:0xcb3790a50 'UISV-canvas-connection' UIStackView:0xcca27ddc0.top == _UILayoutSpacer:0xcbe843600'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb3790af0 'UISV-canvas-connection' UIStackView:0xcca27ddc0.centerY == UIButton:0xcca3ab300.centerY (active)>",
"<NSLayoutConstraint:0xcb3790d70 'UISV-canvas-connection' UIStackView:0xcca27e4c0.top == UIView:0xcca27e300.top (active)>",
"<NSLayoutConstraint:0xcb3790dc0 'UISV-canvas-connection' V:[UIView:0xcca27e140]-(0)-| (active, names: '|':UIStackView:0xcca27e4c0 )>",
"<NSLayoutConstraint:0xcb3790fa0 'UISV-canvas-connection' UIStackView:0xcca3f16c0.top == UIStackView:0xcca27d340.top (active)>",
"<NSLayoutConstraint:0xcb3790ff0 'UISV-canvas-connection' V:[UIStackView:0xcca27e4c0]-(0)-| (active, names: '|':UIStackView:0xcca3f16c0 )>",
"<NSLayoutConstraint:0xcb376bb60 'UISV-spacing' V:[UIView:0xcca27d180]-(5)-[UIView:0xcca27cfc0] (active)>",
"<NSLayoutConstraint:0xcb3790e10 'UISV-spacing' V:[UIView:0xcca27e300]-(5)-[UIView:0xcca27e140] (active)>",
"<NSLayoutConstraint:0xcb3791a40 'UISV-spacing' V:[UIStackView:0xcca27d340]-(4)-[UIStackView:0xcca27ddc0] (active)>",
"<NSLayoutConstraint:0xcb3791b30 'UISV-spacing' V:[UIStackView:0xcca27ddc0]-(4)-[UIStackView:0xcca27e4c0] (active)>",
"<NSLayoutConstraint:0xcb3790870 'UISV-spanning-boundary' _UILayoutSpacer:0xcbe843600'UISV-alignment-spanner'.top <= UIImageView:0xcca22a400.top (active)>",
"<NSLayoutConstraint:0xcb37914f0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca3f1340.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb376aee0 UIImageView:0xcca22a400.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb3790730 UIView:0xcca27f480.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791680 UIView:0xcca288540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791630 UIView:0xcca288380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37910e0 UILabel:0xcb36be680.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb3791d60 UIView:0xcca26d880.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791db0 UIView:0xcca26ea00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791e00 UIView:0xcca26e840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791fe0 V:[UIStackView:0xcca27f800]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca27fd40 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb3790730 UIView:0xcca27f480.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791680 UIView:0xcca288540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791860 UIImageView:0xcca22bc00.height == 30 (active)>",
"<NSLayoutConstraint:0xcb3791db0 UIView:0xcca26ea00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791e00 UIView:0xcca26e840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791fe0 V:[UIStackView:0xcca27f800]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca27fd40 )>",
"<NSLayoutConstraint:0xcb3792030 V:|-(0)-[UIStackView:0xcca27f800] (active, names: '|':UITableViewCellContentView:0xcca27fd40 )>",
"<NSLayoutConstraint:0xcb37935c0 'UISV-alignment' UIButton:0xcca28f000.centerY == UIImageView:0xcca22bc00.centerY (active)>",
"<NSLayoutConstraint:0xcb3792440 'UISV-canvas-connection' UIStackView:0xcca27f640.top == UIView:0xcca27f480.top (active)>",
"<NSLayoutConstraint:0xcb3792490 'UISV-canvas-connection' V:[UIView:0xcca288540]-(0)-| (active, names: '|':UIStackView:0xcca27f640 )>",
"<NSLayoutConstraint:0xcb3793390 'UISV-canvas-connection' UIStackView:0xcca2881c0.top == _UILayoutSpacer:0xcbbce0400'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb3793430 'UISV-canvas-connection' UIStackView:0xcca2881c0.centerY == UIButton:0xcca28f000.centerY (active)>",
"<NSLayoutConstraint:0xcb37936b0 'UISV-canvas-connection' UIStackView:0xcca26ebc0.top == UIView:0xcca26ea00.top (active)>",
"<NSLayoutConstraint:0xcb3793700 'UISV-canvas-connection' V:[UIView:0xcca26e840]-(0)-| (active, names: '|':UIStackView:0xcca26ebc0 )>",
"<NSLayoutConstraint:0xcb37938e0 'UISV-canvas-connection' UIStackView:0xcca27f800.top == UIStackView:0xcca27f640.top (active)>",
"<NSLayoutConstraint:0xcb3793930 'UISV-canvas-connection' V:[UIStackView:0xcca26ebc0]-(0)-| (active, names: '|':UIStackView:0xcca27f800 )>",
"<NSLayoutConstraint:0xcb37924e0 'UISV-spacing' V:[UIView:0xcca27f480]-(5)-[UIView:0xcca288540] (active)>",
"<NSLayoutConstraint:0xcb3793750 'UISV-spacing' V:[UIView:0xcca26ea00]-(5)-[UIView:0xcca26e840] (active)>",
"<NSLayoutConstraint:0xcb37a82d0 'UISV-spacing' V:[UIStackView:0xcca27f640]-(4)-[UIStackView:0xcca2881c0] (active)>",
"<NSLayoutConstraint:0xcb37a83c0 'UISV-spacing' V:[UIStackView:0xcca2881c0]-(4)-[UIStackView:0xcca26ebc0] (active)>",
"<NSLayoutConstraint:0xcb37931b0 'UISV-spanning-boundary' _UILayoutSpacer:0xcbbce0400'UISV-alignment-spanner'.top <= UIImageView:0xcca22bc00.top (active)>",
"<NSLayoutConstraint:0xcb3793e30 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca27fd40.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb3791860 UIImageView:0xcca22bc00.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb3790730 UIView:0xcca27f480.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791680 UIView:0xcca288540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791cc0 UIView:0xcca26dc00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791b80 UILabel:0xcb36bed80.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb3791c70 UIView:0xcca26da40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791db0 UIView:0xcca26ea00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791e00 UIView:0xcca26e840.height == 0 (active)>",
"<NSLayoutConstraint:0xcb3791fe0 V:[UIStackView:0xcca27f800]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca27fd40 )>",
"<NSLayoutConstraint:0xcb3792030 V:|-(0)-[UIStackView:0xcca27f800] (active, names: '|':UITableViewCellContentView:0xcca27fd40 )>",
"<NSLayoutConstraint:0xcb3793660 'UISV-alignment' UIButton:0xcca28f000.centerY == UIStackView:0xcca26ddc0.centerY (active)>",
"<NSLayoutConstraint:0xcb3792440 'UISV-canvas-connection' UIStackView:0xcca27f640.top == UIView:0xcca27f480.top (active)>",
"<NSLayoutConstraint:0xcb3792490 'UISV-canvas-connection' V:[UIView:0xcca288540]-(0)-| (active, names: '|':UIStackView:0xcca27f640 )>",
"<NSLayoutConstraint:0xcb3792ad0 'UISV-canvas-connection' UIStackView:0xcca26ddc0.top == UIView:0xcca26dc00.top (active)>",
"<NSLayoutConstraint:0xcb3792b20 'UISV-canvas-connection' V:[UIView:0xcca26da40]-(0)-| (active, names: '|':UIStackView:0xcca26ddc0 )>",
"<NSLayoutConstraint:0xcb37933e0 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcbbce0400'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca2881c0 )>",
"<NSLayoutConstraint:0xcb3793430 'UISV-canvas-connection' UIStackView:0xcca2881c0.centerY == UIButton:0xcca28f000.centerY (active)>",
"<NSLayoutConstraint:0xcb37936b0 'UISV-canvas-connection' UIStackView:0xcca26ebc0.top == UIView:0xcca26ea00.top (active)>",
"<NSLayoutConstraint:0xcb3793700 'UISV-canvas-connection' V:[UIView:0xcca26e840]-(0)-| (active, names: '|':UIStackView:0xcca26ebc0 )>",
"<NSLayoutConstraint:0xcb37938e0 'UISV-canvas-connection' UIStackView:0xcca27f800.top == UIStackView:0xcca27f640.top (active)>",
"<NSLayoutConstraint:0xcb3793930 'UISV-canvas-connection' V:[UIStackView:0xcca26ebc0]-(0)-| (active, names: '|':UIStackView:0xcca27f800 )>",
"<NSLayoutConstraint:0xcb37924e0 'UISV-spacing' V:[UIView:0xcca27f480]-(5)-[UIView:0xcca288540] (active)>",
"<NSLayoutConstraint:0xcb3792b70 'UISV-spacing' V:[UIView:0xcca26dc00]-(4)-[UILabel:0xcb36bed80] (active)>",
"<NSLayoutConstraint:0xcb3792bc0 'UISV-spacing' V:[UILabel:0xcb36bed80]-(4)-[UIView:0xcca26da40] (active)>",
"<NSLayoutConstraint:0xcb3793750 'UISV-spacing' V:[UIView:0xcca26ea00]-(5)-[UIView:0xcca26e840] (active)>",
"<NSLayoutConstraint:0xcb37a82d0 'UISV-spacing' V:[UIStackView:0xcca27f640]-(4)-[UIStackView:0xcca2881c0] (active)>",
"<NSLayoutConstraint:0xcb37a83c0 'UISV-spacing' V:[UIStackView:0xcca2881c0]-(4)-[UIStackView:0xcca26ebc0] (active)>",
"<NSLayoutConstraint:0xcb3793340 'UISV-spanning-boundary' _UILayoutSpacer:0xcbbce0400'UISV-alignment-spanner'.bottom >= UIStackView:0xcca26ddc0.bottom (active)>",
"<NSLayoutConstraint:0xcb3793e30 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca27fd40.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb3791b80 UILabel:0xcb36bed80.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37a8000 UIView:0xcca436d80.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8050 UIView:0xcca4372c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a80a0 UIView:0xcca436f40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a85f0 UILabel:0xcb36bf100.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37a88c0 UIView:0xcca435500.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8910 UIView:0xcca435a40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8960 UIView:0xcca4356c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8b40 V:[UIStackView:0xcca436300]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca436140 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37a8000 UIView:0xcca436d80.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8050 UIView:0xcca4372c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a87d0 UILabel:0xcb36bf800.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37a8730 UIView:0xcca434a80.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8870 UIView:0xcca434c40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8910 UIView:0xcca435a40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8960 UIView:0xcca4356c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8b40 V:[UIStackView:0xcca436300]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca436140 )>",
"<NSLayoutConstraint:0xcb37a8b90 V:|-(0)-[UIStackView:0xcca436300] (active, names: '|':UITableViewCellContentView:0xcca436140 )>",
"<NSLayoutConstraint:0xcb37aa1c0 'UISV-alignment' UIButton:0xcca28ed00.centerY == UIStackView:0xcca4364c0.centerY (active)>",
"<NSLayoutConstraint:0xcb37a8fa0 'UISV-canvas-connection' UIStackView:0xcca436bc0.top == UIView:0xcca436d80.top (active)>",
"<NSLayoutConstraint:0xcb37a8ff0 'UISV-canvas-connection' V:[UIView:0xcca4372c0]-(0)-| (active, names: '|':UIStackView:0xcca436bc0 )>",
"<NSLayoutConstraint:0xcb37a9630 'UISV-canvas-connection' UIStackView:0xcca4364c0.top == UIView:0xcca434a80.top (active)>",
"<NSLayoutConstraint:0xcb37a9680 'UISV-canvas-connection' V:[UIView:0xcca434c40]-(0)-| (active, names: '|':UIStackView:0xcca4364c0 )>",
"<NSLayoutConstraint:0xcb37a9f40 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3433c00'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca437100 )>",
"<NSLayoutConstraint:0xcb37a9f90 'UISV-canvas-connection' UIStackView:0xcca437100.centerY == UIButton:0xcca28ed00.centerY (active)>",
"<NSLayoutConstraint:0xcb37aa210 'UISV-canvas-connection' UIStackView:0xcca435880.top == UIView:0xcca435a40.top (active)>",
"<NSLayoutConstraint:0xcb37aa260 'UISV-canvas-connection' V:[UIView:0xcca4356c0]-(0)-| (active, names: '|':UIStackView:0xcca435880 )>",
"<NSLayoutConstraint:0xcb37aa440 'UISV-canvas-connection' UIStackView:0xcca436300.top == UIStackView:0xcca436bc0.top (active)>",
"<NSLayoutConstraint:0xcb37aa490 'UISV-canvas-connection' V:[UIStackView:0xcca435880]-(0)-| (active, names: '|':UIStackView:0xcca436300 )>",
"<NSLayoutConstraint:0xcb37a9040 'UISV-spacing' V:[UIView:0xcca436d80]-(5)-[UIView:0xcca4372c0] (active)>",
"<NSLayoutConstraint:0xcb37a96d0 'UISV-spacing' V:[UIView:0xcca434a80]-(4)-[UILabel:0xcb36bf800] (active)>",
"<NSLayoutConstraint:0xcb37a9720 'UISV-spacing' V:[UILabel:0xcb36bf800]-(4)-[UIView:0xcca434c40] (active)>",
"<NSLayoutConstraint:0xcb37aa2b0 'UISV-spacing' V:[UIView:0xcca435a40]-(5)-[UIView:0xcca4356c0] (active)>",
"<NSLayoutConstraint:0xcb37aadf0 'UISV-spacing' V:[UIStackView:0xcca436bc0]-(4)-[UIStackView:0xcca437100] (active)>",
"<NSLayoutConstraint:0xcb37aaee0 'UISV-spacing' V:[UIStackView:0xcca437100]-(4)-[UIStackView:0xcca435880] (active)>",
"<NSLayoutConstraint:0xcb37a9ea0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3433c00'UISV-alignment-spanner'.bottom >= UIStackView:0xcca4364c0.bottom (active)>",
"<NSLayoutConstraint:0xcb37aa990 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca436140.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb37a87d0 UILabel:0xcb36bf800.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37a8000 UIView:0xcca436d80.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8050 UIView:0xcca4372c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8410 UIImageView:0xcca22b800.height == 30 (active)>",
"<NSLayoutConstraint:0xcb37a8910 UIView:0xcca435a40.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8960 UIView:0xcca4356c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8b40 V:[UIStackView:0xcca436300]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca436140 )>",
"<NSLayoutConstraint:0xcb37a8b90 V:|-(0)-[UIStackView:0xcca436300] (active, names: '|':UITableViewCellContentView:0xcca436140 )>",
"<NSLayoutConstraint:0xcb37aa120 'UISV-alignment' UIButton:0xcca28ed00.centerY == UIImageView:0xcca22b800.centerY (active)>",
"<NSLayoutConstraint:0xcb37a8fa0 'UISV-canvas-connection' UIStackView:0xcca436bc0.top == UIView:0xcca436d80.top (active)>",
"<NSLayoutConstraint:0xcb37a8ff0 'UISV-canvas-connection' V:[UIView:0xcca4372c0]-(0)-| (active, names: '|':UIStackView:0xcca436bc0 )>",
"<NSLayoutConstraint:0xcb37a9ef0 'UISV-canvas-connection' UIStackView:0xcca437100.top == _UILayoutSpacer:0xcb3433c00'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb37a9f90 'UISV-canvas-connection' UIStackView:0xcca437100.centerY == UIButton:0xcca28ed00.centerY (active)>",
"<NSLayoutConstraint:0xcb37aa210 'UISV-canvas-connection' UIStackView:0xcca435880.top == UIView:0xcca435a40.top (active)>",
"<NSLayoutConstraint:0xcb37aa260 'UISV-canvas-connection' V:[UIView:0xcca4356c0]-(0)-| (active, names: '|':UIStackView:0xcca435880 )>",
"<NSLayoutConstraint:0xcb37aa440 'UISV-canvas-connection' UIStackView:0xcca436300.top == UIStackView:0xcca436bc0.top (active)>",
"<NSLayoutConstraint:0xcb37aa490 'UISV-canvas-connection' V:[UIStackView:0xcca435880]-(0)-| (active, names: '|':UIStackView:0xcca436300 )>",
"<NSLayoutConstraint:0xcb37a9040 'UISV-spacing' V:[UIView:0xcca436d80]-(5)-[UIView:0xcca4372c0] (active)>",
"<NSLayoutConstraint:0xcb37aa2b0 'UISV-spacing' V:[UIView:0xcca435a40]-(5)-[UIView:0xcca4356c0] (active)>",
"<NSLayoutConstraint:0xcb37aadf0 'UISV-spacing' V:[UIStackView:0xcca436bc0]-(4)-[UIStackView:0xcca437100] (active)>",
"<NSLayoutConstraint:0xcb37aaee0 'UISV-spacing' V:[UIStackView:0xcca437100]-(4)-[UIStackView:0xcca435880] (active)>",
"<NSLayoutConstraint:0xcb37a9d10 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3433c00'UISV-alignment-spanner'.top <= UIImageView:0xcca22b800.top (active)>",
"<NSLayoutConstraint:0xcb37aa990 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca436140.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb37a8410 UIImageView:0xcca22b800.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37a8550 UIView:0xcca4341c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8a50 UIView:0xcca4348c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a9bd0 UIView:0xcca434700.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37aa580 UILabel:0xcb36bfb80.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37ab110 UIView:0xcca2f8000.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab160 UIView:0xcca2f8380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab1b0 UIView:0xcca2f8540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab390 V:[UIStackView:0xcca434e00]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca434fc0 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37a8550 UIView:0xcca4341c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8a50 UIView:0xcca4348c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37aaf30 UILabel:0xcb3760380.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37ab070 UIView:0xcca4379c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab020 UIView:0xcca26e4c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab160 UIView:0xcca2f8380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab1b0 UIView:0xcca2f8540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab390 V:[UIStackView:0xcca434e00]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca434fc0 )>",
"<NSLayoutConstraint:0xcb37ab3e0 V:|-(0)-[UIStackView:0xcca434e00] (active, names: '|':UITableViewCellContentView:0xcca434fc0 )>",
"<NSLayoutConstraint:0xcb37cc690 'UISV-alignment' UIButton:0xcca28f600.centerY == UIStackView:0xcca437800.centerY (active)>",
"<NSLayoutConstraint:0xcb37ab7f0 'UISV-canvas-connection' UIStackView:0xcca434000.top == UIView:0xcca4341c0.top (active)>",
"<NSLayoutConstraint:0xcb37ab840 'UISV-canvas-connection' V:[UIView:0xcca4348c0]-(0)-| (active, names: '|':UIStackView:0xcca434000 )>",
"<NSLayoutConstraint:0xcb37abe80 'UISV-canvas-connection' UIStackView:0xcca437800.top == UIView:0xcca4379c0.top (active)>",
"<NSLayoutConstraint:0xcb37abed0 'UISV-canvas-connection' V:[UIView:0xcca26e4c0]-(0)-| (active, names: '|':UIStackView:0xcca437800 )>",
"<NSLayoutConstraint:0xcb37cc410 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3432b00'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca437480 )>",
"<NSLayoutConstraint:0xcb37cc460 'UISV-canvas-connection' UIStackView:0xcca437480.centerY == UIButton:0xcca28f600.centerY (active)>",
"<NSLayoutConstraint:0xcb37cc6e0 'UISV-canvas-connection' UIStackView:0xcca2f81c0.top == UIView:0xcca2f8380.top (active)>",
"<NSLayoutConstraint:0xcb37cc730 'UISV-canvas-connection' V:[UIView:0xcca2f8540]-(0)-| (active, names: '|':UIStackView:0xcca2f81c0 )>",
"<NSLayoutConstraint:0xcb37cc910 'UISV-canvas-connection' UIStackView:0xcca434e00.top == UIStackView:0xcca434000.top (active)>",
"<NSLayoutConstraint:0xcb37cc960 'UISV-canvas-connection' V:[UIStackView:0xcca2f81c0]-(0)-| (active, names: '|':UIStackView:0xcca434e00 )>",
"<NSLayoutConstraint:0xcb37ab890 'UISV-spacing' V:[UIView:0xcca4341c0]-(5)-[UIView:0xcca4348c0] (active)>",
"<NSLayoutConstraint:0xcb37abf20 'UISV-spacing' V:[UIView:0xcca4379c0]-(4)-[UILabel:0xcb3760380] (active)>",
"<NSLayoutConstraint:0xcb37abf70 'UISV-spacing' V:[UILabel:0xcb3760380]-(4)-[UIView:0xcca26e4c0] (active)>",
"<NSLayoutConstraint:0xcb37cc780 'UISV-spacing' V:[UIView:0xcca2f8380]-(5)-[UIView:0xcca2f8540] (active)>",
"<NSLayoutConstraint:0xcb37cd310 'UISV-spacing' V:[UIStackView:0xcca434000]-(4)-[UIStackView:0xcca437480] (active)>",
"<NSLayoutConstraint:0xcb37cd400 'UISV-spacing' V:[UIStackView:0xcca437480]-(4)-[UIStackView:0xcca2f81c0] (active)>",
"<NSLayoutConstraint:0xcb37cc370 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3432b00'UISV-alignment-spanner'.bottom >= UIStackView:0xcca437800.bottom (active)>",
"<NSLayoutConstraint:0xcb37cce60 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca434fc0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb37aaf30 UILabel:0xcb3760380.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37a8550 UIView:0xcca4341c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37a8a50 UIView:0xcca4348c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37aac60 UIImageView:0xcca300a00.height == 30 (active)>",
"<NSLayoutConstraint:0xcb37ab160 UIView:0xcca2f8380.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab1b0 UIView:0xcca2f8540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ab390 V:[UIStackView:0xcca434e00]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca434fc0 )>",
"<NSLayoutConstraint:0xcb37ab3e0 V:|-(0)-[UIStackView:0xcca434e00] (active, names: '|':UITableViewCellContentView:0xcca434fc0 )>",
"<NSLayoutConstraint:0xcb37cc5f0 'UISV-alignment' UIButton:0xcca28f600.centerY == UIImageView:0xcca300a00.centerY (active)>",
"<NSLayoutConstraint:0xcb37ab7f0 'UISV-canvas-connection' UIStackView:0xcca434000.top == UIView:0xcca4341c0.top (active)>",
"<NSLayoutConstraint:0xcb37ab840 'UISV-canvas-connection' V:[UIView:0xcca4348c0]-(0)-| (active, names: '|':UIStackView:0xcca434000 )>",
"<NSLayoutConstraint:0xcb37cc3c0 'UISV-canvas-connection' UIStackView:0xcca437480.top == _UILayoutSpacer:0xcb3432b00'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb37cc460 'UISV-canvas-connection' UIStackView:0xcca437480.centerY == UIButton:0xcca28f600.centerY (active)>",
"<NSLayoutConstraint:0xcb37cc6e0 'UISV-canvas-connection' UIStackView:0xcca2f81c0.top == UIView:0xcca2f8380.top (active)>",
"<NSLayoutConstraint:0xcb37cc730 'UISV-canvas-connection' V:[UIView:0xcca2f8540]-(0)-| (active, names: '|':UIStackView:0xcca2f81c0 )>",
"<NSLayoutConstraint:0xcb37cc910 'UISV-canvas-connection' UIStackView:0xcca434e00.top == UIStackView:0xcca434000.top (active)>",
"<NSLayoutConstraint:0xcb37cc960 'UISV-canvas-connection' V:[UIStackView:0xcca2f81c0]-(0)-| (active, names: '|':UIStackView:0xcca434e00 )>",
"<NSLayoutConstraint:0xcb37ab890 'UISV-spacing' V:[UIView:0xcca4341c0]-(5)-[UIView:0xcca4348c0] (active)>",
"<NSLayoutConstraint:0xcb37cc780 'UISV-spacing' V:[UIView:0xcca2f8380]-(5)-[UIView:0xcca2f8540] (active)>",
"<NSLayoutConstraint:0xcb37cd310 'UISV-spacing' V:[UIStackView:0xcca434000]-(4)-[UIStackView:0xcca437480] (active)>",
"<NSLayoutConstraint:0xcb37cd400 'UISV-spacing' V:[UIStackView:0xcca437480]-(4)-[UIStackView:0xcca2f81c0] (active)>",
"<NSLayoutConstraint:0xcb37cc1e0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3432b00'UISV-alignment-spanner'.top <= UIImageView:0xcca300a00.top (active)>",
"<NSLayoutConstraint:0xcb37cce60 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca434fc0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb37aac60 UIImageView:0xcca300a00.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37cdf40 UIView:0xcca308e00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ce990 UIView:0xcca308fc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cf700 UIView:0xcca309180.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfa20 UILabel:0xcb3760e00.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37cfcf0 UIView:0xcca309f80.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfd40 UIView:0xcca30a300.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfd90 UIView:0xcca30a4c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cff70 V:[UIStackView:0xcca308a80]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3088c0 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37cdf40 UIView:0xcca308e00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ce990 UIView:0xcca308fc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cf930 UIImageView:0xcca301a00.height == 30 (active)>",
"<NSLayoutConstraint:0xcb37cfd40 UIView:0xcca30a300.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfd90 UIView:0xcca30a4c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cff70 V:[UIStackView:0xcca308a80]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3088c0 )>",
"<NSLayoutConstraint:0xcb37abcf0 V:|-(0)-[UIStackView:0xcca308a80] (active, names: '|':UITableViewCellContentView:0xcca3088c0 )>",
"<NSLayoutConstraint:0xcb2c15450 'UISV-alignment' UIButton:0xcca237300.centerY == UIImageView:0xcca301a00.centerY (active)>",
"<NSLayoutConstraint:0xcb2c142d0 'UISV-canvas-connection' UIStackView:0xcca308c40.top == UIView:0xcca308e00.top (active)>",
"<NSLayoutConstraint:0xcb2c14320 'UISV-canvas-connection' V:[UIView:0xcca308fc0]-(0)-| (active, names: '|':UIStackView:0xcca308c40 )>",
"<NSLayoutConstraint:0xcb2c15220 'UISV-canvas-connection' UIStackView:0xcca309340.top == _UILayoutSpacer:0xcb3432600'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb2c152c0 'UISV-canvas-connection' UIStackView:0xcca309340.centerY == UIButton:0xcca237300.centerY (active)>",
"<NSLayoutConstraint:0xcb2c15540 'UISV-canvas-connection' UIStackView:0xcca30a140.top == UIView:0xcca30a300.top (active)>",
"<NSLayoutConstraint:0xcb2c15590 'UISV-canvas-connection' V:[UIView:0xcca30a4c0]-(0)-| (active, names: '|':UIStackView:0xcca30a140 )>",
"<NSLayoutConstraint:0xcb2c15770 'UISV-canvas-connection' UIStackView:0xcca308a80.top == UIStackView:0xcca308c40.top (active)>",
"<NSLayoutConstraint:0xcb2c157c0 'UISV-canvas-connection' V:[UIStackView:0xcca30a140]-(0)-| (active, names: '|':UIStackView:0xcca308a80 )>",
"<NSLayoutConstraint:0xcb2c14370 'UISV-spacing' V:[UIView:0xcca308e00]-(5)-[UIView:0xcca308fc0] (active)>",
"<NSLayoutConstraint:0xcb2c155e0 'UISV-spacing' V:[UIView:0xcca30a300]-(5)-[UIView:0xcca30a4c0] (active)>",
"<NSLayoutConstraint:0xcb2c16030 'UISV-spacing' V:[UIStackView:0xcca308c40]-(4)-[UIStackView:0xcca309340] (active)>",
"<NSLayoutConstraint:0xcb2c16120 'UISV-spacing' V:[UIStackView:0xcca309340]-(4)-[UIStackView:0xcca30a140] (active)>",
"<NSLayoutConstraint:0xcb2c15040 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3432600'UISV-alignment-spanner'.top <= UIImageView:0xcca301a00.top (active)>",
"<NSLayoutConstraint:0xcb2c15cc0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca3088c0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb37cf930 UIImageView:0xcca301a00.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb37cdf40 UIView:0xcca308e00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37ce990 UIView:0xcca308fc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfb60 UIView:0xcca309c00.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfc00 UILabel:0xcb3761500.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb37cfca0 UIView:0xcca309dc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfd40 UIView:0xcca30a300.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cfd90 UIView:0xcca30a4c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb37cff70 V:[UIStackView:0xcca308a80]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca3088c0 )>",
"<NSLayoutConstraint:0xcb37abcf0 V:|-(0)-[UIStackView:0xcca308a80] (active, names: '|':UITableViewCellContentView:0xcca3088c0 )>",
"<NSLayoutConstraint:0xcb2c154f0 'UISV-alignment' UIButton:0xcca237300.centerY == UIStackView:0xcca309a40.centerY (active)>",
"<NSLayoutConstraint:0xcb2c142d0 'UISV-canvas-connection' UIStackView:0xcca308c40.top == UIView:0xcca308e00.top (active)>",
"<NSLayoutConstraint:0xcb2c14320 'UISV-canvas-connection' V:[UIView:0xcca308fc0]-(0)-| (active, names: '|':UIStackView:0xcca308c40 )>",
"<NSLayoutConstraint:0xcb2c14960 'UISV-canvas-connection' UIStackView:0xcca309a40.top == UIView:0xcca309c00.top (active)>",
"<NSLayoutConstraint:0xcb2c149b0 'UISV-canvas-connection' V:[UIView:0xcca309dc0]-(0)-| (active, names: '|':UIStackView:0xcca309a40 )>",
"<NSLayoutConstraint:0xcb2c15270 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3432600'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca309340 )>",
"<NSLayoutConstraint:0xcb2c152c0 'UISV-canvas-connection' UIStackView:0xcca309340.centerY == UIButton:0xcca237300.centerY (active)>",
"<NSLayoutConstraint:0xcb2c15540 'UISV-canvas-connection' UIStackView:0xcca30a140.top == UIView:0xcca30a300.top (active)>",
"<NSLayoutConstraint:0xcb2c15590 'UISV-canvas-connection' V:[UIView:0xcca30a4c0]-(0)-| (active, names: '|':UIStackView:0xcca30a140 )>",
"<NSLayoutConstraint:0xcb2c15770 'UISV-canvas-connection' UIStackView:0xcca308a80.top == UIStackView:0xcca308c40.top (active)>",
"<NSLayoutConstraint:0xcb2c157c0 'UISV-canvas-connection' V:[UIStackView:0xcca30a140]-(0)-| (active, names: '|':UIStackView:0xcca308a80 )>",
"<NSLayoutConstraint:0xcb2c14370 'UISV-spacing' V:[UIView:0xcca308e00]-(5)-[UIView:0xcca308fc0] (active)>",
"<NSLayoutConstraint:0xcb2c14a00 'UISV-spacing' V:[UIView:0xcca309c00]-(4)-[UILabel:0xcb3761500] (active)>",
"<NSLayoutConstraint:0xcb2c14a50 'UISV-spacing' V:[UILabel:0xcb3761500]-(4)-[UIView:0xcca309dc0] (active)>",
"<NSLayoutConstraint:0xcb2c155e0 'UISV-spacing' V:[UIView:0xcca30a300]-(5)-[UIView:0xcca30a4c0] (active)>",
"<NSLayoutConstraint:0xcb2c16030 'UISV-spacing' V:[UIStackView:0xcca308c40]-(4)-[UIStackView:0xcca309340] (active)>",
"<NSLayoutConstraint:0xcb2c16120 'UISV-spacing' V:[UIStackView:0xcca309340]-(4)-[UIStackView:0xcca30a140] (active)>",
"<NSLayoutConstraint:0xcb2c151d0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3432600'UISV-alignment-spanner'.bottom >= UIStackView:0xcca309a40.bottom (active)>",
"<NSLayoutConstraint:0xcb2c15cc0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca3088c0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb37cfc00 UILabel:0xcb3761500.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb2c14f00 UIView:0xcca30b100.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c15e50 UIView:0xcca30b2c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c15e00 UIView:0xcca30b480.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16300 UILabel:0xcb3761880.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb2c164e0 UIView:0xcca31c1c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16530 UIView:0xcca31c540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16580 UIView:0xcca31c700.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16760 V:[UIStackView:0xcca30ad80]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca30a840 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb2c14f00 UIView:0xcca30b100.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c15e50 UIView:0xcca30b2c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c15810 UIImageView:0xcca303000.height == 30 (active)>",
"<NSLayoutConstraint:0xcb2c16530 UIView:0xcca31c540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16580 UIView:0xcca31c700.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16760 V:[UIStackView:0xcca30ad80]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca30a840 )>",
"<NSLayoutConstraint:0xcb2c167b0 V:|-(0)-[UIStackView:0xcca30ad80] (active, names: '|':UITableViewCellContentView:0xcca30a840 )>",
"<NSLayoutConstraint:0xcb2c17d40 'UISV-alignment' UIButton:0xcca310600.centerY == UIImageView:0xcca303000.centerY (active)>",
"<NSLayoutConstraint:0xcb2c16bc0 'UISV-canvas-connection' UIStackView:0xcca30af40.top == UIView:0xcca30b100.top (active)>",
"<NSLayoutConstraint:0xcb2c16c10 'UISV-canvas-connection' V:[UIView:0xcca30b2c0]-(0)-| (active, names: '|':UIStackView:0xcca30af40 )>",
"<NSLayoutConstraint:0xcb2c17b10 'UISV-canvas-connection' UIStackView:0xcca30b640.top == _UILayoutSpacer:0xcb3431500'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcb2c17bb0 'UISV-canvas-connection' UIStackView:0xcca30b640.centerY == UIButton:0xcca310600.centerY (active)>",
"<NSLayoutConstraint:0xcb2c17e30 'UISV-canvas-connection' UIStackView:0xcca31c380.top == UIView:0xcca31c540.top (active)>",
"<NSLayoutConstraint:0xcb2c17e80 'UISV-canvas-connection' V:[UIView:0xcca31c700]-(0)-| (active, names: '|':UIStackView:0xcca31c380 )>",
"<NSLayoutConstraint:0xcaff28000 'UISV-canvas-connection' UIStackView:0xcca30ad80.top == UIStackView:0xcca30af40.top (active)>",
"<NSLayoutConstraint:0xcaff28050 'UISV-canvas-connection' V:[UIStackView:0xcca31c380]-(0)-| (active, names: '|':UIStackView:0xcca30ad80 )>",
"<NSLayoutConstraint:0xcb2c16c60 'UISV-spacing' V:[UIView:0xcca30b100]-(5)-[UIView:0xcca30b2c0] (active)>",
"<NSLayoutConstraint:0xcb2c17ed0 'UISV-spacing' V:[UIView:0xcca31c540]-(5)-[UIView:0xcca31c700] (active)>",
"<NSLayoutConstraint:0xcaff28a00 'UISV-spacing' V:[UIStackView:0xcca30af40]-(4)-[UIStackView:0xcca30b640] (active)>",
"<NSLayoutConstraint:0xcaff28af0 'UISV-spacing' V:[UIStackView:0xcca30b640]-(4)-[UIStackView:0xcca31c380] (active)>",
"<NSLayoutConstraint:0xcb2c17930 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3431500'UISV-alignment-spanner'.top <= UIImageView:0xcca303000.top (active)>",
"<NSLayoutConstraint:0xcaff28550 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca30a840.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb2c15810 UIImageView:0xcca303000.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcb2c14f00 UIView:0xcca30b100.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c15e50 UIView:0xcca30b2c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16350 UIView:0xcca2fb800.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c163f0 UILabel:0xcb3761f80.height >= 22 (active)>",
"<NSLayoutConstraint:0xcb2c16490 UIView:0xcca31c000.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16530 UIView:0xcca31c540.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16580 UIView:0xcca31c700.height == 0 (active)>",
"<NSLayoutConstraint:0xcb2c16760 V:[UIStackView:0xcca30ad80]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca30a840 )>",
"<NSLayoutConstraint:0xcb2c167b0 V:|-(0)-[UIStackView:0xcca30ad80] (active, names: '|':UITableViewCellContentView:0xcca30a840 )>",
"<NSLayoutConstraint:0xcb2c17de0 'UISV-alignment' UIButton:0xcca310600.centerY == UIStackView:0xcca30bd40.centerY (active)>",
"<NSLayoutConstraint:0xcb2c16bc0 'UISV-canvas-connection' UIStackView:0xcca30af40.top == UIView:0xcca30b100.top (active)>",
"<NSLayoutConstraint:0xcb2c16c10 'UISV-canvas-connection' V:[UIView:0xcca30b2c0]-(0)-| (active, names: '|':UIStackView:0xcca30af40 )>",
"<NSLayoutConstraint:0xcb2c17250 'UISV-canvas-connection' UIStackView:0xcca30bd40.top == UIView:0xcca2fb800.top (active)>",
"<NSLayoutConstraint:0xcb2c172a0 'UISV-canvas-connection' V:[UIView:0xcca31c000]-(0)-| (active, names: '|':UIStackView:0xcca30bd40 )>",
"<NSLayoutConstraint:0xcb2c17b60 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3431500'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca30b640 )>",
"<NSLayoutConstraint:0xcb2c17bb0 'UISV-canvas-connection' UIStackView:0xcca30b640.centerY == UIButton:0xcca310600.centerY (active)>",
"<NSLayoutConstraint:0xcb2c17e30 'UISV-canvas-connection' UIStackView:0xcca31c380.top == UIView:0xcca31c540.top (active)>",
"<NSLayoutConstraint:0xcb2c17e80 'UISV-canvas-connection' V:[UIView:0xcca31c700]-(0)-| (active, names: '|':UIStackView:0xcca31c380 )>",
"<NSLayoutConstraint:0xcaff28000 'UISV-canvas-connection' UIStackView:0xcca30ad80.top == UIStackView:0xcca30af40.top (active)>",
"<NSLayoutConstraint:0xcaff28050 'UISV-canvas-connection' V:[UIStackView:0xcca31c380]-(0)-| (active, names: '|':UIStackView:0xcca30ad80 )>",
"<NSLayoutConstraint:0xcb2c16c60 'UISV-spacing' V:[UIView:0xcca30b100]-(5)-[UIView:0xcca30b2c0] (active)>",
"<NSLayoutConstraint:0xcb2c172f0 'UISV-spacing' V:[UIView:0xcca2fb800]-(4)-[UILabel:0xcb3761f80] (active)>",
"<NSLayoutConstraint:0xcb2c17340 'UISV-spacing' V:[UILabel:0xcb3761f80]-(4)-[UIView:0xcca31c000] (active)>",
"<NSLayoutConstraint:0xcb2c17ed0 'UISV-spacing' V:[UIView:0xcca31c540]-(5)-[UIView:0xcca31c700] (active)>",
"<NSLayoutConstraint:0xcaff28a00 'UISV-spacing' V:[UIStackView:0xcca30af40]-(4)-[UIStackView:0xcca30b640] (active)>",
"<NSLayoutConstraint:0xcaff28af0 'UISV-spacing' V:[UIStackView:0xcca30b640]-(4)-[UIStackView:0xcca31c380] (active)>",
"<NSLayoutConstraint:0xcb2c17ac0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3431500'UISV-alignment-spanner'.bottom >= UIStackView:0xcca30bd40.bottom (active)>",
"<NSLayoutConstraint:0xcaff28550 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca30a840.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcb2c163f0 UILabel:0xcb3761f80.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff286e0 UIView:0xcca31d500.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28690 UIView:0xcca31d6c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28730 UIView:0xcca31d880.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28c80 UILabel:0xcb3762300.height >= 22 (active)>",
"<NSLayoutConstraint:0xcaff28e60 UIView:0xcca31e680.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28eb0 UIView:0xcca31ea00.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28f00 UIView:0xcca31ebc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff290e0 V:[UIStackView:0xcca31d180]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca31cfc0 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff286e0 UIView:0xcca31d500.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28690 UIView:0xcca31d6c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28d70 UILabel:0xcb3762a00.height >= 22 (active)>",
"<NSLayoutConstraint:0xcaff28c30 UIView:0xcca31e300.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28e10 UIView:0xcca31e4c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28eb0 UIView:0xcca31ea00.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28f00 UIView:0xcca31ebc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff290e0 V:[UIStackView:0xcca31d180]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca31cfc0 )>",
"<NSLayoutConstraint:0xcaff29130 V:|-(0)-[UIStackView:0xcca31d180] (active, names: '|':UITableViewCellContentView:0xcca31cfc0 )>",
"<NSLayoutConstraint:0xcaff2a760 'UISV-alignment' UIButton:0xcca310f00.centerY == UIStackView:0xcca31e140.centerY (active)>",
"<NSLayoutConstraint:0xcaff29540 'UISV-canvas-connection' UIStackView:0xcca31d340.top == UIView:0xcca31d500.top (active)>",
"<NSLayoutConstraint:0xcaff29590 'UISV-canvas-connection' V:[UIView:0xcca31d6c0]-(0)-| (active, names: '|':UIStackView:0xcca31d340 )>",
"<NSLayoutConstraint:0xcaff29bd0 'UISV-canvas-connection' UIStackView:0xcca31e140.top == UIView:0xcca31e300.top (active)>",
"<NSLayoutConstraint:0xcaff29c20 'UISV-canvas-connection' V:[UIView:0xcca31e4c0]-(0)-| (active, names: '|':UIStackView:0xcca31e140 )>",
"<NSLayoutConstraint:0xcaff2a4e0 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3432400'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca31da40 )>",
"<NSLayoutConstraint:0xcaff2a530 'UISV-canvas-connection' UIStackView:0xcca31da40.centerY == UIButton:0xcca310f00.centerY (active)>",
"<NSLayoutConstraint:0xcaff2a7b0 'UISV-canvas-connection' UIStackView:0xcca31e840.top == UIView:0xcca31ea00.top (active)>",
"<NSLayoutConstraint:0xcaff2a800 'UISV-canvas-connection' V:[UIView:0xcca31ebc0]-(0)-| (active, names: '|':UIStackView:0xcca31e840 )>",
"<NSLayoutConstraint:0xcaff2a9e0 'UISV-canvas-connection' UIStackView:0xcca31d180.top == UIStackView:0xcca31d340.top (active)>",
"<NSLayoutConstraint:0xcaff2aa30 'UISV-canvas-connection' V:[UIStackView:0xcca31e840]-(0)-| (active, names: '|':UIStackView:0xcca31d180 )>",
"<NSLayoutConstraint:0xcaff295e0 'UISV-spacing' V:[UIView:0xcca31d500]-(5)-[UIView:0xcca31d6c0] (active)>",
"<NSLayoutConstraint:0xcaff29c70 'UISV-spacing' V:[UIView:0xcca31e300]-(4)-[UILabel:0xcb3762a00] (active)>",
"<NSLayoutConstraint:0xcaff29cc0 'UISV-spacing' V:[UILabel:0xcb3762a00]-(4)-[UIView:0xcca31e4c0] (active)>",
"<NSLayoutConstraint:0xcaff2a850 'UISV-spacing' V:[UIView:0xcca31ea00]-(5)-[UIView:0xcca31ebc0] (active)>",
"<NSLayoutConstraint:0xcaff2b250 'UISV-spacing' V:[UIStackView:0xcca31d340]-(4)-[UIStackView:0xcca31da40] (active)>",
"<NSLayoutConstraint:0xcaff2b340 'UISV-spacing' V:[UIStackView:0xcca31da40]-(4)-[UIStackView:0xcca31e840] (active)>",
"<NSLayoutConstraint:0xcaff2a440 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3432400'UISV-alignment-spanner'.bottom >= UIStackView:0xcca31e140.bottom (active)>",
"<NSLayoutConstraint:0xcaff2af30 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca31cfc0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcaff28d70 UILabel:0xcb3762a00.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff286e0 UIView:0xcca31d500.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28690 UIView:0xcca31d6c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff280f0 UIImageView:0xcca303c00.height == 30 (active)>",
"<NSLayoutConstraint:0xcaff28eb0 UIView:0xcca31ea00.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28f00 UIView:0xcca31ebc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff290e0 V:[UIStackView:0xcca31d180]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca31cfc0 )>",
"<NSLayoutConstraint:0xcaff29130 V:|-(0)-[UIStackView:0xcca31d180] (active, names: '|':UITableViewCellContentView:0xcca31cfc0 )>",
"<NSLayoutConstraint:0xcaff2a6c0 'UISV-alignment' UIButton:0xcca310f00.centerY == UIImageView:0xcca303c00.centerY (active)>",
"<NSLayoutConstraint:0xcaff29540 'UISV-canvas-connection' UIStackView:0xcca31d340.top == UIView:0xcca31d500.top (active)>",
"<NSLayoutConstraint:0xcaff29590 'UISV-canvas-connection' V:[UIView:0xcca31d6c0]-(0)-| (active, names: '|':UIStackView:0xcca31d340 )>",
"<NSLayoutConstraint:0xcaff2a490 'UISV-canvas-connection' UIStackView:0xcca31da40.top == _UILayoutSpacer:0xcb3432400'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcaff2a530 'UISV-canvas-connection' UIStackView:0xcca31da40.centerY == UIButton:0xcca310f00.centerY (active)>",
"<NSLayoutConstraint:0xcaff2a7b0 'UISV-canvas-connection' UIStackView:0xcca31e840.top == UIView:0xcca31ea00.top (active)>",
"<NSLayoutConstraint:0xcaff2a800 'UISV-canvas-connection' V:[UIView:0xcca31ebc0]-(0)-| (active, names: '|':UIStackView:0xcca31e840 )>",
"<NSLayoutConstraint:0xcaff2a9e0 'UISV-canvas-connection' UIStackView:0xcca31d180.top == UIStackView:0xcca31d340.top (active)>",
"<NSLayoutConstraint:0xcaff2aa30 'UISV-canvas-connection' V:[UIStackView:0xcca31e840]-(0)-| (active, names: '|':UIStackView:0xcca31d180 )>",
"<NSLayoutConstraint:0xcaff295e0 'UISV-spacing' V:[UIView:0xcca31d500]-(5)-[UIView:0xcca31d6c0] (active)>",
"<NSLayoutConstraint:0xcaff2a850 'UISV-spacing' V:[UIView:0xcca31ea00]-(5)-[UIView:0xcca31ebc0] (active)>",
"<NSLayoutConstraint:0xcaff2b250 'UISV-spacing' V:[UIStackView:0xcca31d340]-(4)-[UIStackView:0xcca31da40] (active)>",
"<NSLayoutConstraint:0xcaff2b340 'UISV-spacing' V:[UIStackView:0xcca31da40]-(4)-[UIStackView:0xcca31e840] (active)>",
"<NSLayoutConstraint:0xcaff2a2b0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3432400'UISV-alignment-spanner'.top <= UIImageView:0xcca303c00.top (active)>",
"<NSLayoutConstraint:0xcaff2af30 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca31cfc0.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcaff280f0 UIImageView:0xcca303c00.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff28190 UIView:0xcca31f9c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28ff0 UIView:0xcca31fb80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2a170 UIView:0xcca31fd40.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b4d0 UILabel:0xcb3762d80.height >= 22 (active)>",
"<NSLayoutConstraint:0xcaff2b6b0 UIView:0xcca324c40.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b700 UIView:0xcca324fc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b750 UIView:0xcca325180.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b930 V:[UIStackView:0xcca31f640]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca31f480 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff28190 UIView:0xcca31f9c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28ff0 UIView:0xcca31fb80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2aad0 UIImageView:0xcca340800.height == 30 (active)>",
"<NSLayoutConstraint:0xcaff2b700 UIView:0xcca324fc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b750 UIView:0xcca325180.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b930 V:[UIStackView:0xcca31f640]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca31f480 )>",
"<NSLayoutConstraint:0xcaff2b980 V:|-(0)-[UIStackView:0xcca31f640] (active, names: '|':UITableViewCellContentView:0xcca31f480 )>",
"<NSLayoutConstraint:0xcaff40dc0 'UISV-alignment' UIButton:0xcca311800.centerY == UIImageView:0xcca340800.centerY (active)>",
"<NSLayoutConstraint:0xcaff2bd90 'UISV-canvas-connection' UIStackView:0xcca31f800.top == UIView:0xcca31f9c0.top (active)>",
"<NSLayoutConstraint:0xcaff2bde0 'UISV-canvas-connection' V:[UIView:0xcca31fb80]-(0)-| (active, names: '|':UIStackView:0xcca31f800 )>",
"<NSLayoutConstraint:0xcaff40b90 'UISV-canvas-connection' UIStackView:0xcca324000.top == _UILayoutSpacer:0xcb3431400'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcaff40c30 'UISV-canvas-connection' UIStackView:0xcca324000.centerY == UIButton:0xcca311800.centerY (active)>",
"<NSLayoutConstraint:0xcaff40eb0 'UISV-canvas-connection' UIStackView:0xcca324e00.top == UIView:0xcca324fc0.top (active)>",
"<NSLayoutConstraint:0xcaff40f00 'UISV-canvas-connection' V:[UIView:0xcca325180]-(0)-| (active, names: '|':UIStackView:0xcca324e00 )>",
"<NSLayoutConstraint:0xcaff410e0 'UISV-canvas-connection' UIStackView:0xcca31f640.top == UIStackView:0xcca31f800.top (active)>",
"<NSLayoutConstraint:0xcaff41130 'UISV-canvas-connection' V:[UIStackView:0xcca324e00]-(0)-| (active, names: '|':UIStackView:0xcca31f640 )>",
"<NSLayoutConstraint:0xcaff2be30 'UISV-spacing' V:[UIView:0xcca31f9c0]-(5)-[UIView:0xcca31fb80] (active)>",
"<NSLayoutConstraint:0xcaff40f50 'UISV-spacing' V:[UIView:0xcca324fc0]-(5)-[UIView:0xcca325180] (active)>",
"<NSLayoutConstraint:0xcaff419f0 'UISV-spacing' V:[UIStackView:0xcca31f800]-(4)-[UIStackView:0xcca324000] (active)>",
"<NSLayoutConstraint:0xcaff41ae0 'UISV-spacing' V:[UIStackView:0xcca324000]-(4)-[UIStackView:0xcca324e00] (active)>",
"<NSLayoutConstraint:0xcaff409b0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3431400'UISV-alignment-spanner'.top <= UIImageView:0xcca340800.top (active)>",
"<NSLayoutConstraint:0xcaff41630 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca31f480.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcaff2aad0 UIImageView:0xcca340800.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff28190 UIView:0xcca31f9c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff28ff0 UIView:0xcca31fb80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b480 UIView:0xcca3248c0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b5c0 UILabel:0xcb3763480.height >= 22 (active)>",
"<NSLayoutConstraint:0xcaff2b660 UIView:0xcca324a80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b700 UIView:0xcca324fc0.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b750 UIView:0xcca325180.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff2b930 V:[UIStackView:0xcca31f640]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca31f480 )>",
"<NSLayoutConstraint:0xcaff2b980 V:|-(0)-[UIStackView:0xcca31f640] (active, names: '|':UITableViewCellContentView:0xcca31f480 )>",
"<NSLayoutConstraint:0xcaff40e60 'UISV-alignment' UIButton:0xcca311800.centerY == UIStackView:0xcca324700.centerY (active)>",
"<NSLayoutConstraint:0xcaff2bd90 'UISV-canvas-connection' UIStackView:0xcca31f800.top == UIView:0xcca31f9c0.top (active)>",
"<NSLayoutConstraint:0xcaff2bde0 'UISV-canvas-connection' V:[UIView:0xcca31fb80]-(0)-| (active, names: '|':UIStackView:0xcca31f800 )>",
"<NSLayoutConstraint:0xcaff402d0 'UISV-canvas-connection' UIStackView:0xcca324700.top == UIView:0xcca3248c0.top (active)>",
"<NSLayoutConstraint:0xcaff40320 'UISV-canvas-connection' V:[UIView:0xcca324a80]-(0)-| (active, names: '|':UIStackView:0xcca324700 )>",
"<NSLayoutConstraint:0xcaff40be0 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3431400'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca324000 )>",
"<NSLayoutConstraint:0xcaff40c30 'UISV-canvas-connection' UIStackView:0xcca324000.centerY == UIButton:0xcca311800.centerY (active)>",
"<NSLayoutConstraint:0xcaff40eb0 'UISV-canvas-connection' UIStackView:0xcca324e00.top == UIView:0xcca324fc0.top (active)>",
"<NSLayoutConstraint:0xcaff40f00 'UISV-canvas-connection' V:[UIView:0xcca325180]-(0)-| (active, names: '|':UIStackView:0xcca324e00 )>",
"<NSLayoutConstraint:0xcaff410e0 'UISV-canvas-connection' UIStackView:0xcca31f640.top == UIStackView:0xcca31f800.top (active)>",
"<NSLayoutConstraint:0xcaff41130 'UISV-canvas-connection' V:[UIStackView:0xcca324e00]-(0)-| (active, names: '|':UIStackView:0xcca31f640 )>",
"<NSLayoutConstraint:0xcaff2be30 'UISV-spacing' V:[UIView:0xcca31f9c0]-(5)-[UIView:0xcca31fb80] (active)>",
"<NSLayoutConstraint:0xcaff40370 'UISV-spacing' V:[UIView:0xcca3248c0]-(4)-[UILabel:0xcb3763480] (active)>",
"<NSLayoutConstraint:0xcaff403c0 'UISV-spacing' V:[UILabel:0xcb3763480]-(4)-[UIView:0xcca324a80] (active)>",
"<NSLayoutConstraint:0xcaff40f50 'UISV-spacing' V:[UIView:0xcca324fc0]-(5)-[UIView:0xcca325180] (active)>",
"<NSLayoutConstraint:0xcaff419f0 'UISV-spacing' V:[UIStackView:0xcca31f800]-(4)-[UIStackView:0xcca324000] (active)>",
"<NSLayoutConstraint:0xcaff41ae0 'UISV-spacing' V:[UIStackView:0xcca324000]-(4)-[UIStackView:0xcca324e00] (active)>",
"<NSLayoutConstraint:0xcaff40b40 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3431400'UISV-alignment-spanner'.bottom >= UIStackView:0xcca324700.bottom (active)>",
"<NSLayoutConstraint:0xcaff41630 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca31f480.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcaff2b5c0 UILabel:0xcb3763480.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff40870 UIView:0xcca325f80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff417c0 UIView:0xcca326140.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41770 UIView:0xcca326300.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41c70 UILabel:0xcb3763800.height >= 22 (active)>",
"<NSLayoutConstraint:0xcaff41e50 UIView:0xcca327100.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41ea0 UIView:0xcca327480.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41ef0 UIView:0xcca327640.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff420d0 V:[UIStackView:0xcca325c00]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca325a40 )>",
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff40870 UIView:0xcca325f80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff417c0 UIView:0xcca326140.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41d60 UILabel:0xcb2c60000.height >= 22 (active)>",
"<NSLayoutConstraint:0xcaff41c20 UIView:0xcca326d80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41e00 UIView:0xcca326f40.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41ea0 UIView:0xcca327480.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41ef0 UIView:0xcca327640.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff420d0 V:[UIStackView:0xcca325c00]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca325a40 )>",
"<NSLayoutConstraint:0xcaff42120 V:|-(0)-[UIStackView:0xcca325c00] (active, names: '|':UITableViewCellContentView:0xcca325a40 )>",
"<NSLayoutConstraint:0xcaff43750 'UISV-alignment' UIButton:0xcca312100.centerY == UIStackView:0xcca326bc0.centerY (active)>",
"<NSLayoutConstraint:0xcaff42530 'UISV-canvas-connection' UIStackView:0xcca325dc0.top == UIView:0xcca325f80.top (active)>",
"<NSLayoutConstraint:0xcaff42580 'UISV-canvas-connection' V:[UIView:0xcca326140]-(0)-| (active, names: '|':UIStackView:0xcca325dc0 )>",
"<NSLayoutConstraint:0xcaff42bc0 'UISV-canvas-connection' UIStackView:0xcca326bc0.top == UIView:0xcca326d80.top (active)>",
"<NSLayoutConstraint:0xcaff42c10 'UISV-canvas-connection' V:[UIView:0xcca326f40]-(0)-| (active, names: '|':UIStackView:0xcca326bc0 )>",
"<NSLayoutConstraint:0xcaff434d0 'UISV-canvas-connection' V:[_UILayoutSpacer:0xcb3431c00'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0xcca3264c0 )>",
"<NSLayoutConstraint:0xcaff43520 'UISV-canvas-connection' UIStackView:0xcca3264c0.centerY == UIButton:0xcca312100.centerY (active)>",
"<NSLayoutConstraint:0xcaff437a0 'UISV-canvas-connection' UIStackView:0xcca3272c0.top == UIView:0xcca327480.top (active)>",
"<NSLayoutConstraint:0xcaff437f0 'UISV-canvas-connection' V:[UIView:0xcca327640]-(0)-| (active, names: '|':UIStackView:0xcca3272c0 )>",
"<NSLayoutConstraint:0xcaff439d0 'UISV-canvas-connection' UIStackView:0xcca325c00.top == UIStackView:0xcca325dc0.top (active)>",
"<NSLayoutConstraint:0xcaff43a20 'UISV-canvas-connection' V:[UIStackView:0xcca3272c0]-(0)-| (active, names: '|':UIStackView:0xcca325c00 )>",
"<NSLayoutConstraint:0xcaff425d0 'UISV-spacing' V:[UIView:0xcca325f80]-(5)-[UIView:0xcca326140] (active)>",
"<NSLayoutConstraint:0xcaff42c60 'UISV-spacing' V:[UIView:0xcca326d80]-(4)-[UILabel:0xcb2c60000] (active)>",
"<NSLayoutConstraint:0xcaff42cb0 'UISV-spacing' V:[UILabel:0xcb2c60000]-(4)-[UIView:0xcca326f40] (active)>",
"<NSLayoutConstraint:0xcaff43840 'UISV-spacing' V:[UIView:0xcca327480]-(5)-[UIView:0xcca327640] (active)>",
"<NSLayoutConstraint:0xcaff483c0 'UISV-spacing' V:[UIStackView:0xcca325dc0]-(4)-[UIStackView:0xcca3264c0] (active)>",
"<NSLayoutConstraint:0xcaff484b0 'UISV-spacing' V:[UIStackView:0xcca3264c0]-(4)-[UIStackView:0xcca3272c0] (active)>",
"<NSLayoutConstraint:0xcaff43430 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3431c00'UISV-alignment-spanner'.bottom >= UIStackView:0xcca326bc0.bottom (active)>",
"<NSLayoutConstraint:0xcaff43f20 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca325a40.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcaff41d60 UILabel:0xcb2c60000.height >= 22 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0xcaff40870 UIView:0xcca325f80.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff417c0 UIView:0xcca326140.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff411d0 UIImageView:0xcca341400.height == 30 (active)>",
"<NSLayoutConstraint:0xcaff41ea0 UIView:0xcca327480.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff41ef0 UIView:0xcca327640.height == 0 (active)>",
"<NSLayoutConstraint:0xcaff420d0 V:[UIStackView:0xcca325c00]-(0)-| (active, names: '|':UITableViewCellContentView:0xcca325a40 )>",
"<NSLayoutConstraint:0xcaff42120 V:|-(0)-[UIStackView:0xcca325c00] (active, names: '|':UITableViewCellContentView:0xcca325a40 )>",
"<NSLayoutConstraint:0xcaff436b0 'UISV-alignment' UIButton:0xcca312100.centerY == UIImageView:0xcca341400.centerY (active)>",
"<NSLayoutConstraint:0xcaff42530 'UISV-canvas-connection' UIStackView:0xcca325dc0.top == UIView:0xcca325f80.top (active)>",
"<NSLayoutConstraint:0xcaff42580 'UISV-canvas-connection' V:[UIView:0xcca326140]-(0)-| (active, names: '|':UIStackView:0xcca325dc0 )>",
"<NSLayoutConstraint:0xcaff43480 'UISV-canvas-connection' UIStackView:0xcca3264c0.top == _UILayoutSpacer:0xcb3431c00'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0xcaff43520 'UISV-canvas-connection' UIStackView:0xcca3264c0.centerY == UIButton:0xcca312100.centerY (active)>",
"<NSLayoutConstraint:0xcaff437a0 'UISV-canvas-connection' UIStackView:0xcca3272c0.top == UIView:0xcca327480.top (active)>",
"<NSLayoutConstraint:0xcaff437f0 'UISV-canvas-connection' V:[UIView:0xcca327640]-(0)-| (active, names: '|':UIStackView:0xcca3272c0 )>",
"<NSLayoutConstraint:0xcaff439d0 'UISV-canvas-connection' UIStackView:0xcca325c00.top == UIStackView:0xcca325dc0.top (active)>",
"<NSLayoutConstraint:0xcaff43a20 'UISV-canvas-connection' V:[UIStackView:0xcca3272c0]-(0)-| (active, names: '|':UIStackView:0xcca325c00 )>",
"<NSLayoutConstraint:0xcaff425d0 'UISV-spacing' V:[UIView:0xcca325f80]-(5)-[UIView:0xcca326140] (active)>",
"<NSLayoutConstraint:0xcaff43840 'UISV-spacing' V:[UIView:0xcca327480]-(5)-[UIView:0xcca327640] (active)>",
"<NSLayoutConstraint:0xcaff483c0 'UISV-spacing' V:[UIStackView:0xcca325dc0]-(4)-[UIStackView:0xcca3264c0] (active)>",
"<NSLayoutConstraint:0xcaff484b0 'UISV-spacing' V:[UIStackView:0xcca3264c0]-(4)-[UIStackView:0xcca3272c0] (active)>",
"<NSLayoutConstraint:0xcaff432a0 'UISV-spanning-boundary' _UILayoutSpacer:0xcb3431c00'UISV-alignment-spanner'.top <= UIImageView:0xcca341400.top (active)>",
"<NSLayoutConstraint:0xcaff43f20 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0xcca325a40.height == 40.04 (active)>"
)

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xcaff411d0 UIImageView:0xcca341400.height == 30 (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
cannot add handler to 4 from 1 - dropping
cannot add handler to 3 from 1 - dropping
INFO: [OAMapRendererView 0xcbfafea00] Rendering suspended
WebContent[ 97 731 ] 0x123058100 - [sessionID=1] WebProcess::updateFreezerStatus: isFreezable=1, error=-1
cannot add handler to 4 from 1 - dropping
cannot add handler to 3 from 1 - dropping

}
let screenElementsSection = UIMenu(title: "", options: .displayInline, children: [screenElementsAction])
let profileActionsSection = UIMenu(title: "", options: .displayInline, children: [copyAction, resetAction])
let menu = UIMenu(title: "", children: [screenElementsSection, profileActionsSection])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

composedMenu?

let screenElementsViewController = ScreenElementsViewController(appMode: appMode)
screenElementsViewController.delegate = self
let navigationController = UINavigationController(rootViewController: screenElementsViewController)
navigationController.modalPresentationStyle = .pageSheet

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the expected behavior on iPad?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

}
}

func iconName(for screenLayoutMode: ScreenLayoutMode) -> String {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you use the generated icon?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I set it to panelsLayoutRow.iconName as string value

}
}

func imageName(for screenLayoutMode: ScreenLayoutMode) -> String {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

up

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I set it to previewRow.iconName as string value


init(appMode: OAApplicationMode) {
private var allPreferenceLayoutModes: [NSNumber?] {
var preferenceLayoutModes: [NSNumber?] = [nil]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need [NSNumber?] here instead of [ScreenLayoutMode?]?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private var allPreferenceLayoutModes: [NSNumber?] {
[nil] + ScreenLayoutMode.allCases.map { NSNumber(value: $0.rawValue) }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need [NSNumber?] here instead of [ScreenLayoutMode?]?

we need it to fit android behaviour on objective c side

filterModes: Int(kWidgetModeMatchingPanels),
panels: panels,
layoutMode: preferenceLayoutMode)
for widgetInfo in widgetInfos! {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

widgetInfos!

widgetsVisibility.removeAll(where: { $0 == key })
widgetsVisibility.removeAll(where: { $0 == COLLAPSED_PREFIX + key })
widgetsVisibility.removeAll(where: { $0 == HIDE_PREFIX + key })
widgetsVisibility.removeAll(where: { $0 == "" })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty entries are now filtered out in widgetsVisibility(_:screenLayoutMode:) using .filter { !$0.isEmpty } when parsing the preference. The array returned here therefore contains no empty strings, so this additional cleanup was redundant. It fits android behaviour

static let rightPanel = WidgetsPanel("ic_custom_screen_side_right", title: localizedString("map_widget_right"))
static let topPanel = WidgetsPanel("ic_custom_screen_side_top", title: localizedString("top_widgets_panel"))
static let bottomPanel = WidgetsPanel("ic_custom_screen_side_bottom", title: localizedString("bottom_widgets_panel"))
static let leftPanel = WidgetsPanel("ic_custom_screen_side_left",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use from asset

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. We need string format for func iconName(for screenLayoutMode: ScreenLayoutMode) -> String that is used for row.iconName = panel.iconName(for: screenLayoutMode)

func getWidgetOrder(_ widgetId: String, appMode: OAApplicationMode) -> Int {
return getPagedOrder(widgetId, appMode: appMode).1

private func getRtlPanel(rtl: Bool) -> WidgetsPanel {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private func rtlPanel(isRtl: Bool) -> WidgetsPanel

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guard rtl else { return self }

switch self {
case .leftPanel:
    return .rightPanel
case .rightPanel:
    return .leftPanel
case .topPanel, .bottomPanel:
    return self
}

UIImage(named: "ic_custom20_screen_side_bottom")!])
let useLandscapeIcons = screenLayoutMode == .landscape
&& OAAppSettings.sharedManager().useSeparateLayouts.get(selectedAppMode)
let iconNames = useLandscapeIcons

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asset name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow to set different widget layout for Landscape / Portrait

4 participants