2013-05-02 3 views
7

Я понимаю, что XCode поймает unsatifyable NSLayoutConstraints и предоставит вам некоторую информацию об этом, однако я не знаю, как взять адреса памяти элементов управления/ограничений и сопоставить их с которые имеют проблемы.Сопоставление адреса памяти неудовлетворительных NSLayoutConstraints с элементами управления пользовательского интерфейса

Мое приложение довольно большое (около 20 экранов), некоторые из них большие UIViewControllers с несколькими контроллерами детского представления внутри них. Некоторые из них - UITableViews с пользовательскими ячейками и UICollectionViews с пользовательскими ячейками. У меня ад времени лавируя вниз причину этой ошибки (что происходит при вращении ландшафтном)

Вот информация из моей консоли:

2013-05-02 11:18:53.225 Smile[7519:c07] 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. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x16083b60 h=-&- v=-&- UIView:0xa5a1d00.width == UIWindow:0xa09eee0.width>", 
    "<NSLayoutConstraint:0xa5a2180 V:[UIView:0xa59f160]-(954)-| (Names: '|':UIView:0xa5a1d00)>", 
    "<NSLayoutConstraint:0xa5a2140 V:|-(0)-[UIView:0xa59f160] (Names: '|':UIView:0xa5a1d00)>", 
    "<NSAutoresizingMaskLayoutConstraint:0xa593340 h=--- v=--- H:[UIWindow:0xa09eee0(768)]>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xa5a2180 V:[UIView:0xa59f160]-(954)-| (Names: '|':UIView:0xa5a1d00)> 

Break on objc_exception_throw to catch this in the debugger. 
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful. 

Как вы можете видеть, есть память адреса указаны. Вставка их в панель поиска окна просмотра не показывает многого. Кроме того, просеивая потоки и очереди вызовов, я получаю только разобранный код на этой точке останова (контрольная точка исключения).

ответ

0

Вы можете попробовать использовать visualizeConstraints:, как упомянуто here, и посмотреть, можете ли вы найти плохие ограничения таким образом.

+0

visualizeConstraints работает только на OS X –

+0

Упс! По какой-то причине я думал, что UILayoutConstraint - вещь, и поэтому я думал, что это на Mac. Наверное, я недостаточно внимательно прочитал вопрос! –

4

Короткий ответ на самом деле не так, OS X имеет свойство идентификатора, которое может быть установлено в представлении, которое используется NSLayoutConstraint, чтобы помочь идентифицировать представления, но это еще не существует на iOS.

Однако есть функция «работать», чтобы реализовать что-то подобное на iOS, но это некрасиво. Сначала вы должны указать имя для каждого представления, которое выполняется в категории UIView. Затем вам нужно обновить вывод для описания NSLayoutConstraint, чтобы использовать новые теги.

@interface NSLayoutConstraint (Nametags) 
- (NSString *)asciiArtDescription; 
@end 

@interface UIView (Nametags) 
@property (nonatomic, strong) NSString *nametag; 
@end 

Затем обеспечить реализацию следующим образом изменить выход NSLayout

#import <objc/objc-runtime.h> 

static const char nametag_key; 
@implementation NSLayoutConstraint (Nametags) 

- (NSString *)description { 
    NSMutableString *myDescription = [NSMutableString stringWithFormat:@"%@, ", [self asciiArtDescription]]; 
    UIView *firstView = (UIView *)[self firstItem]; 
    if (firstView) { 
     [myDescription appendFormat:@"First View: 0x%0x: %@, ", (int)firstView, firstView.nametag]; 
    } 

    UIView *secondView = (UIView *)[self secondItem]; 
    if (secondView) { 
     [myDescription appendFormat:@"Second View: 0x%0x: %@", (int)secondView, secondView.nametag]; 
    } 

    return myDescription; 
} 
@end 

@implementation UIView (Nametags) 
- (id) nametag { 
    return objc_getAssociatedObject(self, (void *) &nametag_key); 
} 

- (void)setNametag:(NSString *) theNametag { 
    objc_setAssociatedObject(self, (void *) &nametag_key, theNametag, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 
@end 

Тогда вы сможете установить имена ваших взглядов, как так

self.view.nametag = @"MyUsefulName"; 

Или определить их в IB

nametag in IB

Наконец, когда вы когда-либо отказываетесь от ограничений, вы получите имена, которые вы предоставили на выходе.

"V:|-(202)-[UIView:0x75606f0], First View: 0x75606f0: Blue View, Second View: 0x7560bd0: (null)", 
"V:[UIView:0x75606f0]-(72)-|, First View: 0x7560bd0: (null), Second View: 0x75606f0: Blue View", 
"V:[UIView:0x7560bd0(548)], First View: 0x7560bd0: (null), " 

Вы должны использовать этот код в ваш отладки строит, не отправить его в приложение, потому что он обращается к методу частный [NSLayoutConstraint asciiArtDescription].

+0

Интересная техника. Это может быть полезно, если вы знаете об этом с самого начала и сделаете его частью стандартной стандартной процедуры. Я подозреваю несколько элементов управления, поэтому я применил этот techinque и посмотрю, что произойдет. – VaporwareWolf

+0

Действительно интересный подход. Полезным дополнением является просто использование существующего свойства accessibilityLabel '' UIView', а не создание нового свойства. Вы все равно должны заполнять свойство accessibilityLabel. :) –

+0

Этот метод объясняется также в http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html, в разделе Debug – giampaolo

6

Я нашел вид решения благодаря этим сайтам: Debugging iOS AutoLayout Issues и Dancing with the Debugger. Благодаря консоли Xcode вы можете определить, из какого представления возникает проблема.

Решение:

  • Шаг 1:

    • Открыть Breakpoint Navigator (Cmd + 7)
    • Нажмите на кнопку 'Добавить' в нижнем левом углу
    • Выбрать ' Добавить Символическую точку останова '
    • Где указано «Символ» в UIViewAlertForUnsatisfiableConstraints
  • Шаг 2: Запустите проект. Когда консоль печатает Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7fc82d3e18a0 H:[UIView:0x7fc82aba1210(768)]>, скопируйте адрес памяти вида (0x7fc82aba1210 здесь).

  • Шаг 3: Изменение фона этой точки зрения, чтобы знать, какой именно с этой командой в консоли: e (void)[0x7fc82d3e18a0 setBackgroundColor:[UIColor redColor]]

  • Шаг 4: Продолжить программу и увидеть обновленный интерфейс. Представление с красным цветом фона является рассматриваемым видом.

  • Шаг 5: Вернитесь к своей IB и найдите, какое ограничение является проблемой на этом представлении.

+1

Шаг 3 был замечательный! –

Смежные вопросы