Skip to content

Commit 6024a81

Browse files
author
Andreas Goese
committed
Re-enabled iOS 7 support
1 parent ae2b180 commit 6024a81

File tree

3 files changed

+83
-53
lines changed

3 files changed

+83
-53
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A wonderful layout component called the [`UIStackView` was introduced with *iOS
44
`UIStackView` requires *iOS 9*, but we're not ready to make our apps require *iOS 9+* just yet. In the meanwhile, we developers are eager to try this component in our apps right now! This is why I created this replica of the `UIStackView`, called the `TZStackView` (TZ = Tom van Zummeren, my initials). I created this component very carefully, tested every single corner case and matched the results against the *real* `UIStackView` with automated `XCTestCases`.
55

66
## Features
7-
- ✅ Compatible with **iOS 8.x** or later
7+
- ✅ Compatible with **iOS 7.x** or later
88
- ✅ Supports the complete API of `UIStackView` including **all** *distribution* and *alignment* options
99
- ✅ Supports animating the `hidden` property of the *arranged subviews*
1010
- ❌ Supports *Storyboard*

TZStackView.xcodeproj/project.pbxproj

+4-2
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@
405405
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
406406
GCC_WARN_UNUSED_FUNCTION = YES;
407407
GCC_WARN_UNUSED_VARIABLE = YES;
408-
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
408+
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
409409
MTL_ENABLE_DEBUG_INFO = YES;
410410
ONLY_ACTIVE_ARCH = YES;
411411
SDKROOT = iphoneos;
@@ -443,7 +443,7 @@
443443
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
444444
GCC_WARN_UNUSED_FUNCTION = YES;
445445
GCC_WARN_UNUSED_VARIABLE = YES;
446-
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
446+
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
447447
MTL_ENABLE_DEBUG_INFO = NO;
448448
SDKROOT = iphoneos;
449449
VALIDATE_PRODUCT = YES;
@@ -456,6 +456,7 @@
456456
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
457457
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
458458
INFOPLIST_FILE = TZStackViewDemo/Info.plist;
459+
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
459460
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
460461
PRODUCT_BUNDLE_IDENTIFIER = "nl.tomvanzummeren.$(PRODUCT_NAME:rfc1034identifier)";
461462
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -500,6 +501,7 @@
500501
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
501502
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
502503
INFOPLIST_FILE = TZStackViewDemo/Info.plist;
504+
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
503505
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
504506
PRODUCT_BUNDLE_IDENTIFIER = "nl.tomvanzummeren.$(PRODUCT_NAME:rfc1034identifier)";
505507
PRODUCT_NAME = "$(TARGET_NAME)";

TZStackView/TZStackView.swift

+78-50
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,10 @@ public class TZStackView: UIView {
220220
stackViewConstraints += createMatchEdgesContraints(arrangedSubviews)
221221
stackViewConstraints += createFirstAndLastViewMatchEdgesContraints()
222222

223-
if alignment == .FirstBaseline && axis == .Horizontal {
224-
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
223+
if #available(iOS 8, *) {
224+
if alignment == .FirstBaseline && axis == .Horizontal {
225+
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
226+
}
225227
}
226228

227229
if distribution == .FillEqually {
@@ -255,8 +257,10 @@ public class TZStackView: UIView {
255257
switch axis {
256258
case .Horizontal:
257259
stackViewConstraints.append(constraint(item: self, attribute: .Width, toItem: nil, attribute: .NotAnAttribute, priority: 49))
258-
if alignment == .FirstBaseline {
259-
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
260+
if #available(iOS 8, *) {
261+
if alignment == .FirstBaseline {
262+
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
263+
}
260264
}
261265
case .Vertical:
262266
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
@@ -281,8 +285,10 @@ public class TZStackView: UIView {
281285
switch axis {
282286
case .Horizontal:
283287
stackViewConstraints.append(constraint(item: self, attribute: .Width, toItem: nil, attribute: .NotAnAttribute, priority: 49))
284-
if alignment == .FirstBaseline {
285-
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
288+
if #available(iOS 8, *) {
289+
if alignment == .FirstBaseline {
290+
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
291+
}
286292
}
287293
case .Vertical:
288294
stackViewConstraints.append(constraint(item: self, attribute: .Height, toItem: nil, attribute: .NotAnAttribute, priority: 49))
@@ -313,17 +319,24 @@ public class TZStackView: UIView {
313319
stackViewConstraints += createSurroundingSpacerViewConstraints(spacerViews[0], views: visibleArrangedSubviews)
314320
}
315321

316-
if layoutMarginsRelativeArrangement {
317-
if spacerViews.count > 0 {
318-
stackViewConstraints.append(constraint(item: self, attribute: .BottomMargin, toItem: spacerViews[0]))
319-
stackViewConstraints.append(constraint(item: self, attribute: .LeftMargin, toItem: spacerViews[0]))
320-
stackViewConstraints.append(constraint(item: self, attribute: .RightMargin, toItem: spacerViews[0]))
321-
stackViewConstraints.append(constraint(item: self, attribute: .TopMargin, toItem: spacerViews[0]))
322+
if #available(iOS 8, *) {
323+
if layoutMarginsRelativeArrangement {
324+
if spacerViews.count > 0 {
325+
stackViewConstraints.append(constraint(item: self, attribute: .BottomMargin, toItem: spacerViews[0]))
326+
stackViewConstraints.append(constraint(item: self, attribute: .LeftMargin, toItem: spacerViews[0]))
327+
stackViewConstraints.append(constraint(item: self, attribute: .RightMargin, toItem: spacerViews[0]))
328+
stackViewConstraints.append(constraint(item: self, attribute: .TopMargin, toItem: spacerViews[0]))
329+
}
322330
}
323331
}
324332
}
325333

326-
NSLayoutConstraint.activateConstraints(subviewConstraints + stackViewConstraints)
334+
let constraintsToActivate = subviewConstraints + stackViewConstraints
335+
if #available(iOS 8.0, *) {
336+
NSLayoutConstraint.activateConstraints(constraintsToActivate)
337+
} else {
338+
addConstraints(constraintsToActivate)
339+
}
327340

328341
super.updateConstraints()
329342
}
@@ -467,41 +480,50 @@ public class TZStackView: UIView {
467480
private func createMatchEdgesContraints(views: [UIView]) -> [NSLayoutConstraint] {
468481
var constraints = [NSLayoutConstraint]()
469482

470-
switch axis {
471-
case .Horizontal:
472-
switch alignment {
473-
case .Fill:
474-
constraints += equalAttributes(views: views, attribute: .Bottom)
475-
constraints += equalAttributes(views: views, attribute: .Top)
476-
case .Center:
477-
constraints += equalAttributes(views: views, attribute: .CenterY)
478-
case .Leading:
479-
constraints += equalAttributes(views: views, attribute: .Top)
480-
case .Trailing:
481-
constraints += equalAttributes(views: views, attribute: .Bottom)
482-
case .FirstBaseline:
483-
constraints += equalAttributes(views: views, attribute: .FirstBaseline)
484-
case .LastBaseline:
483+
switch (alignment, axis) {
484+
case (.Fill, .Horizontal): // Fill alignment
485+
constraints += equalAttributes(views: views, attribute: .Bottom)
486+
constraints += equalAttributes(views: views, attribute: .Top)
487+
case (.Fill, .Vertical):
488+
constraints += equalAttributes(views: views, attribute: .Leading)
489+
constraints += equalAttributes(views: views, attribute: .Trailing)
490+
491+
case (.Center, .Horizontal): // Center alignment
492+
constraints += equalAttributes(views: views, attribute: .CenterY)
493+
case (.Center, .Vertical):
494+
constraints += equalAttributes(views: views, attribute: .CenterX)
495+
496+
case (.Leading, .Horizontal): // Leading & Top alignment
497+
constraints += equalAttributes(views: views, attribute: .Top)
498+
case (.Leading, .Vertical):
499+
constraints += equalAttributes(views: views, attribute: .Leading)
500+
501+
case (.Trailing, .Horizontal): // Trailing and Bottom alignment
502+
constraints += equalAttributes(views: views, attribute: .Bottom)
503+
case (.Trailing, .Vertical):
504+
constraints += equalAttributes(views: views, attribute: .Trailing)
505+
506+
case (.LastBaseline, .Horizontal): // Last-Baseline alignment, works only on horizontal axis
507+
if #available(iOS 8, *) {
485508
constraints += equalAttributes(views: views, attribute: .LastBaseline)
509+
} else {
510+
constraints += equalAttributes(views: views, attribute: .Baseline)
486511
}
487-
488-
case .Vertical:
489-
switch alignment {
490-
case .Fill:
491-
constraints += equalAttributes(views: views, attribute: .Leading)
492-
constraints += equalAttributes(views: views, attribute: .Trailing)
493-
case .Center:
494-
constraints += equalAttributes(views: views, attribute: .CenterX)
495-
case .Leading:
496-
constraints += equalAttributes(views: views, attribute: .Leading)
497-
case .Trailing:
498-
constraints += equalAttributes(views: views, attribute: .Trailing)
499-
case .FirstBaseline:
500-
constraints += []
501-
case .LastBaseline:
512+
case (.LastBaseline, .Vertical):
513+
constraints += []
514+
default: break
515+
}
516+
517+
if #available(iOS 8, *) { // First-Baseline alignment requires iOS 8+
518+
switch (alignment, axis) {
519+
case (.FirstBaseline, .Horizontal): // First-Baseline alignment, works only on horizontal axis
520+
constraints += equalAttributes(views: views, attribute: .FirstBaseline)
521+
case (.FirstBaseline, .Vertical):
502522
constraints += []
523+
default: break
503524
}
504525
}
526+
505527
return constraints
506528
}
507529

@@ -515,21 +537,27 @@ public class TZStackView: UIView {
515537

516538
var topView = arrangedSubviews.first!
517539
var bottomView = arrangedSubviews.first!
540+
518541
if spacerViews.count > 0 {
519-
if alignment == .Center {
542+
switch (alignment, axis) {
543+
case (.Center, _):
520544
topView = spacerViews[0]
521545
bottomView = spacerViews[0]
522-
} else if alignment == .Top || alignment == .Leading {
546+
case (.Leading, _):
523547
bottomView = spacerViews[0]
524-
} else if alignment == .Bottom || alignment == .Trailing {
548+
case (.Trailing, _):
525549
topView = spacerViews[0]
526-
} else if alignment == .FirstBaseline {
527-
switch axis {
528-
case .Horizontal:
550+
default: break
551+
}
552+
553+
if #available(iOS 8, *) {
554+
switch (alignment, axis) {
555+
case (.FirstBaseline, .Horizontal):
529556
bottomView = spacerViews[0]
530-
case .Vertical:
557+
case (.FirstBaseline, .Vertical):
531558
topView = spacerViews[0]
532559
bottomView = spacerViews[0]
560+
default: break
533561
}
534562
}
535563
}

0 commit comments

Comments
 (0)