mirror of https://github.com/SnapKit/SnapKit
Begin support for LayoutGuide constraint maker
This commit is contained in:
parent
4018d4bd12
commit
dc304472aa
|
@ -33,6 +33,7 @@
|
|||
EE235FC31C5785DC00C08960 /* ConstraintLayoutSupportDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE235FBF1C5785DC00C08960 /* ConstraintLayoutSupportDSL.swift */; };
|
||||
EE235FC81C5785E200C08960 /* ConstraintView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE235FC61C5785E200C08960 /* ConstraintView+Extensions.swift */; };
|
||||
EE4910991B19A40200A54F1F /* SnapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEBCC9D819CC627D0083B827 /* SnapKit.framework */; };
|
||||
EE6898CB1DA7B3A100D47F33 /* LayoutConstraintItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE6898CA1DA7B3A100D47F33 /* LayoutConstraintItem.swift */; };
|
||||
EECDB3741AC0C9B6006BBC11 /* SnapKit.h in Headers */ = {isa = PBXBuildFile; fileRef = EECDB3661AC0C95C006BBC11 /* SnapKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
EECDB3931AC0CB52006BBC11 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EECDB36A1AC0C95C006BBC11 /* Tests.swift */; };
|
||||
EEF68F9E1D78492400980C26 /* ConstraintLayoutGuideDSL.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF68F9D1D78492400980C26 /* ConstraintLayoutGuideDSL.swift */; };
|
||||
|
@ -70,6 +71,7 @@
|
|||
EE235FBE1C5785DC00C08960 /* ConstraintViewDSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConstraintViewDSL.swift; sourceTree = "<group>"; };
|
||||
EE235FBF1C5785DC00C08960 /* ConstraintLayoutSupportDSL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConstraintLayoutSupportDSL.swift; sourceTree = "<group>"; };
|
||||
EE235FC61C5785E200C08960 /* ConstraintView+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ConstraintView+Extensions.swift"; sourceTree = "<group>"; };
|
||||
EE6898CA1DA7B3A100D47F33 /* LayoutConstraintItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayoutConstraintItem.swift; sourceTree = "<group>"; };
|
||||
EE94F6081AC0F10A008767FF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
EE94F60A1AC0F10F008767FF /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
EEBCC9D819CC627D0083B827 /* SnapKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SnapKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -184,6 +186,7 @@
|
|||
EE235F6A1C5785C600C08960 /* ConstraintAttributes.swift */,
|
||||
EE235F6B1C5785C600C08960 /* ConstraintItem.swift */,
|
||||
EE235F6C1C5785C600C08960 /* LayoutConstraint.swift */,
|
||||
EE6898CA1DA7B3A100D47F33 /* LayoutConstraintItem.swift */,
|
||||
);
|
||||
name = Models;
|
||||
sourceTree = "<group>";
|
||||
|
@ -372,6 +375,7 @@
|
|||
EE235F761C5785C600C08960 /* ConstraintConfig.swift in Sources */,
|
||||
EE235F6D1C5785C600C08960 /* Constraint.swift in Sources */,
|
||||
EE235F791C5785C600C08960 /* ConstraintView.swift in Sources */,
|
||||
EE6898CB1DA7B3A100D47F33 /* LayoutConstraintItem.swift in Sources */,
|
||||
EE235FB21C5785D400C08960 /* ConstraintMakerPriortizable.swift in Sources */,
|
||||
EE235F8B1C5785C600C08960 /* LayoutConstraint.swift in Sources */,
|
||||
EE235FA31C5785CE00C08960 /* ConstraintInsetTarget.swift in Sources */,
|
||||
|
|
|
@ -73,7 +73,7 @@ public class Constraint {
|
|||
let layoutToAttributes = self.to.attributes.layoutAttributes
|
||||
|
||||
// get layout from
|
||||
let layoutFrom: ConstraintView = self.from.view!
|
||||
let layoutFrom = self.from.layoutConstraintItem!
|
||||
|
||||
// get relation
|
||||
let layoutRelation = self.relation.layoutRelation
|
||||
|
@ -247,12 +247,12 @@ public class Constraint {
|
|||
}
|
||||
|
||||
internal func activateIfNeeded(updatingExisting: Bool = false) {
|
||||
guard let view = self.from.view else {
|
||||
print("WARNING: SnapKit failed to get from view from constraint. Activate will be a no-op.")
|
||||
guard let item = self.from.layoutConstraintItem else {
|
||||
print("WARNING: SnapKit failed to get from item from constraint. Activate will be a no-op.")
|
||||
return
|
||||
}
|
||||
let layoutConstraints = self.layoutConstraints
|
||||
let existingLayoutConstraints = view.snp.constraints.map({ $0.layoutConstraints }).reduce([]) { $0 + $1 }
|
||||
let existingLayoutConstraints = item.constraints.map({ $0.layoutConstraints }).reduce([]) { $0 + $1 }
|
||||
|
||||
if updatingExisting {
|
||||
for layoutConstraint in layoutConstraints {
|
||||
|
@ -266,17 +266,17 @@ public class Constraint {
|
|||
}
|
||||
} else {
|
||||
NSLayoutConstraint.activate(layoutConstraints)
|
||||
view.snp.add(constraints: [self])
|
||||
item.add(constraints: [self])
|
||||
}
|
||||
}
|
||||
|
||||
internal func deactivateIfNeeded() {
|
||||
guard let view = self.from.view else {
|
||||
print("WARNING: SnapKit failed to get from view from constraint. Deactivate will be a no-op.")
|
||||
guard let item = self.from.layoutConstraintItem else {
|
||||
print("WARNING: SnapKit failed to get from item from constraint. Deactivate will be a no-op.")
|
||||
return
|
||||
}
|
||||
let layoutConstraints = self.layoutConstraints
|
||||
NSLayoutConstraint.deactivate(layoutConstraints)
|
||||
view.snp.remove(constraints: [self])
|
||||
item.remove(constraints: [self])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
public class ConstraintDescription {
|
||||
|
||||
internal let view: ConstraintView
|
||||
internal let item: LayoutConstraintItem
|
||||
internal var attributes: ConstraintAttributes
|
||||
internal var relation: ConstraintRelation? = nil
|
||||
internal var sourceLocation: (String, UInt)? = nil
|
||||
|
@ -45,7 +45,7 @@ public class ConstraintDescription {
|
|||
let sourceLocation = self.sourceLocation else {
|
||||
return nil
|
||||
}
|
||||
let from = ConstraintItem(target: self.view, attributes: self.attributes)
|
||||
let from = ConstraintItem(target: self.item as AnyObject, attributes: self.attributes)
|
||||
|
||||
return Constraint(
|
||||
from: from,
|
||||
|
@ -61,8 +61,8 @@ public class ConstraintDescription {
|
|||
|
||||
// MARK: Initialization
|
||||
|
||||
internal init(view: ConstraintView, attributes: ConstraintAttributes) {
|
||||
self.view = view
|
||||
internal init(item: LayoutConstraintItem, attributes: ConstraintAttributes) {
|
||||
self.item = item
|
||||
self.attributes = attributes
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ public class ConstraintItem: Equatable {
|
|||
self.attributes = attributes
|
||||
}
|
||||
|
||||
internal var view: ConstraintView? {
|
||||
return self.target as? ConstraintView
|
||||
internal var layoutConstraintItem: LayoutConstraintItem? {
|
||||
return self.target as? LayoutConstraintItem
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,22 +143,22 @@ public class ConstraintMaker {
|
|||
return self.makeExtendableWithAttributes(.centerWithinMargins)
|
||||
}
|
||||
|
||||
private let view: ConstraintView
|
||||
private let item: LayoutConstraintItem
|
||||
private var descriptions = [ConstraintDescription]()
|
||||
|
||||
internal init(view: ConstraintView) {
|
||||
self.view = view
|
||||
self.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
internal init(item: LayoutConstraintItem) {
|
||||
self.item = item
|
||||
self.item.prepare()
|
||||
}
|
||||
|
||||
internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable {
|
||||
let description = ConstraintDescription(view: self.view, attributes: attributes)
|
||||
let description = ConstraintDescription(item: self.item, attributes: attributes)
|
||||
self.descriptions.append(description)
|
||||
return ConstraintMakerExtendable(description)
|
||||
}
|
||||
|
||||
internal static func prepareConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
|
||||
let maker = ConstraintMaker(view: view)
|
||||
internal static func prepareConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
|
||||
let maker = ConstraintMaker(item: item)
|
||||
closure(maker)
|
||||
let constraints = maker.descriptions
|
||||
.map { $0.constraint }
|
||||
|
@ -167,8 +167,8 @@ public class ConstraintMaker {
|
|||
return constraints
|
||||
}
|
||||
|
||||
internal static func makeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
|
||||
let maker = ConstraintMaker(view: view)
|
||||
internal static func makeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
|
||||
let maker = ConstraintMaker(item: item)
|
||||
closure(maker)
|
||||
let constraints = maker.descriptions
|
||||
.map { $0.constraint }
|
||||
|
@ -179,18 +179,18 @@ public class ConstraintMaker {
|
|||
}
|
||||
}
|
||||
|
||||
internal static func remakeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
|
||||
self.removeConstraints(view: view)
|
||||
self.makeConstraints(view: view, closure: closure)
|
||||
internal static func remakeConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
|
||||
self.removeConstraints(item: item)
|
||||
self.makeConstraints(item: item, closure: closure)
|
||||
}
|
||||
|
||||
internal static func updateConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
|
||||
guard view.snp.constraints.count > 0 else {
|
||||
self.makeConstraints(view: view, closure: closure)
|
||||
internal static func updateConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) {
|
||||
guard item.constraints.count > 0 else {
|
||||
self.makeConstraints(item: item, closure: closure)
|
||||
return
|
||||
}
|
||||
|
||||
let maker = ConstraintMaker(view: view)
|
||||
let maker = ConstraintMaker(item: item)
|
||||
closure(maker)
|
||||
let constraints = maker.descriptions
|
||||
.map { $0.constraint }
|
||||
|
@ -201,8 +201,8 @@ public class ConstraintMaker {
|
|||
}
|
||||
}
|
||||
|
||||
internal static func removeConstraints(view: ConstraintView) {
|
||||
let constraints = view.snp.constraints
|
||||
internal static func removeConstraints(item: LayoutConstraintItem) {
|
||||
let constraints = item.constraints
|
||||
for constraint in constraints {
|
||||
constraint.deactivateIfNeeded()
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class ConstraintMakerRelatable {
|
|||
|
||||
@discardableResult
|
||||
public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
|
||||
guard let other = self.description.view.superview else {
|
||||
guard let other = self.description.item.superview else {
|
||||
fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.")
|
||||
}
|
||||
return self.relatedTo(other, relation: .equal, file: file, line: line)
|
||||
|
@ -89,7 +89,7 @@ public class ConstraintMakerRelatable {
|
|||
|
||||
@discardableResult
|
||||
public func lessThanOrEqualToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
|
||||
guard let other = self.description.view.superview else {
|
||||
guard let other = self.description.item.superview else {
|
||||
fatalError("Expected superview but found nil when attempting make constraint `lessThanOrEqualToSuperview`.")
|
||||
}
|
||||
return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
|
||||
|
@ -102,7 +102,7 @@ public class ConstraintMakerRelatable {
|
|||
|
||||
@discardableResult
|
||||
public func greaterThanOrEqualToSuperview(_ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
|
||||
guard let other = self.description.view.superview else {
|
||||
guard let other = self.description.item.superview else {
|
||||
fatalError("Expected superview but found nil when attempting make constraint `greaterThanOrEqualToSuperview`.")
|
||||
}
|
||||
return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
|
||||
|
|
|
@ -32,27 +32,25 @@ public struct ConstraintViewDSL: ConstraintAttributesDSL {
|
|||
|
||||
@discardableResult
|
||||
public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
|
||||
return ConstraintMaker.prepareConstraints(view: self.view, closure: closure)
|
||||
return ConstraintMaker.prepareConstraints(item: self.view, closure: closure)
|
||||
}
|
||||
|
||||
public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
|
||||
ConstraintMaker.makeConstraints(view: self.view, closure: closure)
|
||||
ConstraintMaker.makeConstraints(item: self.view, closure: closure)
|
||||
}
|
||||
|
||||
public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
|
||||
ConstraintMaker.remakeConstraints(view: self.view, closure: closure)
|
||||
ConstraintMaker.remakeConstraints(item: self.view, closure: closure)
|
||||
}
|
||||
|
||||
public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
|
||||
ConstraintMaker.updateConstraints(view: self.view, closure: closure)
|
||||
ConstraintMaker.updateConstraints(item: self.view, closure: closure)
|
||||
}
|
||||
|
||||
public func removeConstraints() {
|
||||
ConstraintMaker.removeConstraints(view: self.view)
|
||||
ConstraintMaker.removeConstraints(item: self.view)
|
||||
}
|
||||
|
||||
|
||||
|
||||
public var contentHuggingHorizontalPriority: Float {
|
||||
get {
|
||||
return self.view.contentHuggingPriority(for: .horizontal)
|
||||
|
@ -100,36 +98,4 @@ public struct ConstraintViewDSL: ConstraintAttributesDSL {
|
|||
|
||||
}
|
||||
|
||||
internal var constraints: [Constraint] {
|
||||
return self.constraintsHashTable.allObjects
|
||||
}
|
||||
|
||||
internal func add(constraints: [Constraint]) {
|
||||
let hashTable = self.constraintsHashTable
|
||||
for constraint in constraints {
|
||||
hashTable.add(constraint)
|
||||
}
|
||||
}
|
||||
|
||||
internal func remove(constraints: [Constraint]) {
|
||||
let hashTable = self.constraintsHashTable
|
||||
for constraint in constraints {
|
||||
hashTable.remove(constraint)
|
||||
}
|
||||
}
|
||||
|
||||
private var constraintsHashTable: NSHashTable<Constraint> {
|
||||
let constraints: NSHashTable<Constraint>
|
||||
|
||||
if let existing = objc_getAssociatedObject(self.view, &constraintsKey) as? NSHashTable<Constraint> {
|
||||
constraints = existing
|
||||
} else {
|
||||
constraints = NSHashTable<Constraint>()
|
||||
objc_setAssociatedObject(self.view, &constraintsKey, constraints, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||
}
|
||||
return constraints
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
private var constraintsKey: UInt8 = 0
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// SnapKit
|
||||
//
|
||||
// Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#if os(iOS) || os(tvOS)
|
||||
import UIKit
|
||||
#else
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
|
||||
public protocol LayoutConstraintItem: class {
|
||||
}
|
||||
|
||||
extension ConstraintLayoutGuide : LayoutConstraintItem {
|
||||
}
|
||||
|
||||
extension ConstraintView : LayoutConstraintItem {
|
||||
}
|
||||
|
||||
|
||||
extension LayoutConstraintItem {
|
||||
|
||||
internal func prepare() {
|
||||
if let view = self as? ConstraintView {
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
}
|
||||
|
||||
internal var superview: ConstraintView? {
|
||||
if let view = self as? ConstraintView {
|
||||
return view.superview
|
||||
}
|
||||
|
||||
if #available(iOS 9.0, *), let guide = self as? ConstraintLayoutGuide {
|
||||
return guide.owningView
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
internal var constraints: [Constraint] {
|
||||
return self.constraintsHashTable.allObjects
|
||||
}
|
||||
|
||||
internal func add(constraints: [Constraint]) {
|
||||
let hashTable = self.constraintsHashTable
|
||||
for constraint in constraints {
|
||||
hashTable.add(constraint)
|
||||
}
|
||||
}
|
||||
|
||||
internal func remove(constraints: [Constraint]) {
|
||||
let hashTable = self.constraintsHashTable
|
||||
for constraint in constraints {
|
||||
hashTable.remove(constraint)
|
||||
}
|
||||
}
|
||||
|
||||
private var constraintsHashTable: NSHashTable<Constraint> {
|
||||
let constraints: NSHashTable<Constraint>
|
||||
|
||||
if let existing = objc_getAssociatedObject(self, &constraintsKey) as? NSHashTable<Constraint> {
|
||||
constraints = existing
|
||||
} else {
|
||||
constraints = NSHashTable<Constraint>()
|
||||
objc_setAssociatedObject(self, &constraintsKey, constraints, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||
}
|
||||
return constraints
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
private var constraintsKey: UInt8 = 0
|
Loading…
Reference in New Issue