it-swarm.com.ru

Получить ссылку на NSLayoutConstraint, используя идентификатор, установленный в раскадровке

Я устанавливал ограничения кнопки, используя раскадровку. Я видел опцию «Идентификатор» в свойствах ограничения.

Screenshot of constraint's properties

Я хочу сделать ссылку на это ограничение, чтобы изменить его значение в коде, чтобы переместить объект.

Как я могу получить ссылку на эту NSLayoutContraint из этого идентификатора.

Я прочитал документацию, она была написана так

@interface NSLayoutConstraint (NSIdentifier)
/* For ease in debugging, name a constraint by setting its identifier, which will be printed in the constraint's description.
 Identifiers starting with UI and NS are reserved by the system.
 */
@property (nullable, copy) NSString *identifier NS_AVAILABLE_IOS(7_0);

@end

Поэтому я понял, что это для отладки. 

Что если я захочу получить его и использовать? Я видел эту ссылку, но не было дано удовлетворительного ответа: Как получить идентификатор NSLayoutConstraint по его указателю?

12
Sam Shaikh

В Свифт 3 ,

 let filteredConstraints = button.constraints.filter { $0.identifier == "identifier" }
 if let yourConstraint = filteredConstraints.first {
      // DO YOUR LOGIC HERE
 }
22
Venk

Swift 3

Я написал быстрое расширение NSView, которое прекрасно с этим справляется.

extension NSView {
    func constraint(withIdentifier: String) -> NSLayoutConstraint? {
        return self.constraints.filter { $0.identifier == withIdentifier }.first
    }
}

Использование:

if let c = button.constraint(withIdentifier: "my-button-width") {
    // do stuff with c
}
9
quemeful

Я предполагаю, что у вас есть настроенная розетка для кнопки, поэтому у вас есть доступная ссылка на нее. Итак, сначала извлеките ограничения вида из вашей кнопки. Затем выполните цикл по массиву и на каждой итерации сравнивайте свойство идентификатора каждого ограничения со значением, которое вы ввели в Интерфейсном Разработчике. Похоже, вы кодируете в Objective-C, поэтому пример кода Objective-C приведен ниже. Измените @ "identifier" на любое значение, которое вы установите в Интерфейсном Разработчике.

NSArray *constraints = [button constraints];
int count = [constraints count];
int index = 0;
BOOL found = NO;

while (!found && index < count) {
    NSLayoutConstraint *constraint = constraints[index];
    if ( [constraint.identifier isEqualToString:@"identifier"] ) {
        //save the reference to constraint
        found = YES;
    }

    index++;
}
8
strwils

Вы можете экстраполировать логику, представленную в предыдущем ответе, в расширение.

extension UIView {
    /// Returns the first constraint with the given identifier, if available.
    ///
    /// - Parameter identifier: The constraint identifier.
    func constraintWithIdentifier(_ identifier: String) -> NSLayoutConstraint? {
        return self.constraints.first { $0.identifier == identifier }
    }
}

Затем вы можете получить доступ к любому ограничению в любом месте, используя:

myView.constraintWithIdentifier("myConstraintIdentifier")

2
Isaiah Turner

Я упростила поиск и добавила в список предков суперпредставлений:

+ (NSLayoutConstraint *) findConstraintNamed:(NSString *)identifierTarget startWith:(UIView *)aView;    
{    
    // walk upward from item through ancestors  
    UIView *currentView = aView;            

    while (currentView != nil)    
    {    
        NSArray *constraints = [currentView constraints];    
        NSInteger foundConstraintIndex = [constraints indexOfObjectPassingTest:^BOOL(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {   
            return [((NSLayoutConstraint *)obj).identifier isEqualToString:identifierTarget];    
        }];


        if (foundConstraintIndex != NSNotFound)    
        {    
            return constraints[foundConstraintIndex];    
        }                

        // not found, so walk up the ancestor chain    
        currentView = currentView.superview;    
    }    

    return nil;  // not found anywhere in item or ancestors!  :(    
}
0
software evolved

Для изменения размера набора кнопок в контейнере общего вида это работает. Каждое подпредставление/кнопка должно использовать общий идентификатор (например, «высота»).

@IBAction func btnPressed(_ sender: UIButton) {
    for button in self.btnView.subviews{
        for constraint in button.constraints{
            if constraint.identifier == "height"{
                constraint.constant = constraint.constant == 0 ? 30:0
            }
        }
    }
    UIView.animate(withDuration: 0.3) { () -> Void in
        self.view.layoutIfNeeded()
    }
}
0
Craig Jarman