Внешний вид сайта:

Как победить Excluded Constraints с помощью RubyGem

Как победить Excluded Constraints с помощью RubyGem

Во время разработки iOS/OSX-приложений непременно приходится использовать Interface Builder и Auto Layout. В приложениях со сложными интерфейсом и в приложениях, находящихся в разработке, достаточно давно и часто появляется проблема с большим количеством «исключенных констрейнов». Storyboard грузится необоснованно долго, а во время перехода между сценами можно успеть сходить за кофе.

Но, казалось бы, интерфейс всех контроллеров такой же незамысловатый, как и в релизе полгода назад. Что же случилось? Тем, кто использовал Size Classes, сразу понятно, что интерфейс — не такая простая штука, как кажется. Он ведет себя по-разному в разных ориентациях и на разных дисплеях. Делает он это, потому что некоторые constraints применяются только в определенной ситуации.

Это значит, что в остальных ситуациях эти constraints не используются. У Xcode Interface Builder есть особенность, которая помогает при разработке сложных интерфейсов и мешает при разработке простых. Если добавить constraint к какому-то UIView и затем удалить его из Xcode Inspector (а чаще всего это — самый удобный путь), Xcode не удалит его, а лишь сложит в список неиспользуемых на случай, если понадобится для другого дисплея или ориентации.

Иногда, если развернуть все группы constraints, можно ужаснуться происходящему в storyboard-файле:



Больше половины constraints лежат в «корзине» и ждут, пока их добавят к определенному дисплею или ориентации или удалят. А до тех пор — съедают драгоценные секунды загрузки файла и оставшиеся нервные клетки разработчика.

Что же делать?

Можно открывать по очереди все свои storyboard- и xib-файлы, в них открывать всех наследников UIView и, убедившись, что этот constraint не используется для Size Classes, удалить их, используя Document Outline

А можно предоставить эту скучную, не имеющую права на ошибку работу умному Ruby-скрипту. Итак, нам найти все storyboard- и xib-файлы в проекте:

```
files = Dir.glob("**/*.{storyboard,xib}")
files.each{ |file|  cleanupConstraints(file)}
```

Готово, теперь в этих файлах надо найти исключенные constraints:

```
require 'nokogiri'

def cleanupConstraints(file)
    f = File.open(file)
    doc = Nokogiri::XML(f)
    f.close
    excluded = doc.xpath('//exclude')
end
```

Еще надо не забыть про Size Classes и оставить на местах все constraints, которые включены хоть в одну комбинацию «дисплей/ориентация».

```
require 'nokogiri'

def cleanupConstraints(file)
    f = File.open(file)
    doc = Nokogiri::XML(f)
    f.close
    excluded = doc.xpath('//exclude')
    included = doc.xpath('//include')
   
    result = []
    excluded.each do |node|
        found = false
        for includedNode in included
            if node.attr('reference') == includedNode.attr('reference')
                found = true
                break
            end
        end
        if !found
            result.push(node)
            nodeID = node.attr('reference')
            constraints = doc.xpath("//constraint[@id='#{nodeID}']")
            result += constraints
        end
    end
    if result.count > 0
        f1 = File.open(file, 'w')
        result.each{ |node| node.remove }
        f1.write(doc.to_xml)   
        f1.close   
        p "removed #{result.count} constraint(s) from #{file}"
    end
end
```

Маленькая победа, но как использовать этот скрипт? Ответ прост — создать RubyGem. Для создания Gem есть несколько путей, я использовал описанный здесь guides.rubygems.org/make-your-own-gem. Теперь очистить проект (или даже все проекты разом!) можно, установив Gem

```
$ gem install constraintClean
```

В директории своего проекта (или в директории со всеми своими проектами) выполнив

```
$ constraintClean
```

И это прекрасно!

Комментарии

Нет комментариев. Ваш будет первым!