compatible with iOS 11

This commit is contained in:
caiyuanpeng 2017-10-13 16:59:00 +08:00
parent ec5c88e7b3
commit 5db392e14c
9 changed files with 194 additions and 66 deletions

1
.swift-version Normal file
View File

@ -0,0 +1 @@
3.0

View File

@ -12,10 +12,14 @@ import UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let sel = NSSelectorFromString("setContentInsetAdjustmentBehavior:")
if UIScrollView().responds(to: sel) {
UIScrollView.appearance().perform(sel, with: 2)
}
return true
}

View File

@ -92,6 +92,7 @@ class AppStoreViewController: UITableViewController {
self.tableView.estimatedRowHeight = 84
self.tableView.register(AppStoreCell.self, forCellReuseIdentifier: "cell")
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 34, 0)
let path = Bundle.main.path(forResource: "appList", ofType: "plist")
appList = NSArray(contentsOfFile: path!) as? Array<Dictionary<String, Any>>

View File

@ -41,7 +41,7 @@ class SignupViewController: BaseViewController {
self.view.bg("#184367")
let iphone5 = UIScreen.main.bounds.width == 320
let card = View.bg("white").radius(4).embedIn(self.view, iphone5 ? 40 : 60, 30)
let card = View.bg("white").radius(4).embedIn(self.view, iphone5 ? 40 : "60", 30)
let inputStyle = Styles.pin(40, .lowHugging).font(14)
Styles("separator").bg("#C7C7CD").pin(1)
@ -68,7 +68,7 @@ class SignupViewController: BaseViewController {
Button.str("X").font(13).color("#D2E0E8").bg("#EDF2F5").radius(-1).pin(16, 16, .maxX(-10), .y(10)).addTo(card)
Button.str("HELP").font(13).padding(10).pin(.centerX(0), .maxY(-5)).addTo(self.view)
Button.str("HELP").font(13).padding(10).pin(.centerX(0), .maxY("-5")).addTo(self.view)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

View File

@ -47,7 +47,7 @@ class StackViewController: BaseViewController {
self.stack.axis = self.stack.axis == .vertical ? .horizontal : .vertical
})
HStack("<-->", addView, attachGap, gap, align, axis, "<-->").gap(8).embedIn(self.view, nil, 0, 0, 0)
HStack("<-->", addView, attachGap, gap, align, axis, "<-->").gap(8).embedIn(self.view, nil, 0, "0", 0)
}
override func setupUI() {

View File

@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "Cupcake"
s.version = "1.1.0"
s.version = "1.1.1"
s.summary = "An easy way to create and layout UI components for iOS."
s.description = <<-DESC

View File

@ -90,6 +90,8 @@ public class CPKStackView: UIView {
addAndActivateConstraintsForView(at: index)
}
self.disableLayoutMarginsAdjustment(for: view)
} else if let array = sub as? [Any] {
for i in 0..<array.count {
insertArrangedSubview(item: array[i], at: min(index + i, self.arrangedSubviews.count))
@ -122,6 +124,7 @@ public class CPKStackView: UIView {
public override init(frame: CGRect) {
super.init(frame: frame)
self.layoutMargins = UIEdgeInsets.zero
self.disableLayoutMarginsAdjustment(for: self)
}
public required init?(coder aDecoder: NSCoder) {
@ -640,6 +643,17 @@ public class CPKStackView: UIView {
removeAndDeactivateAllConstriants()
addAndActivateConstraintsForAll()
}
private func disableLayoutMarginsAdjustment(for view: UIView) {
// if #available(iOS 11, *) {
// view.insetsLayoutMarginsFromSafeArea = false
// }
let sel = NSSelectorFromString("setInsetsLayoutMarginsFromSafeArea:")
if view.responds(to: sel) {
view.perform(sel, with: nil)
}
}
}

View File

@ -55,7 +55,7 @@ public extension UIView {
.radius(-1) //passing negative number means using auto rounding
*/
@discardableResult public func radius(_ cornerRadius: CGFloat) -> Self {
if cornerRadius >= 0 {
if cornerRadius >= 0.1 && cornerRadius < 9999999 {
self.layer.cornerRadius = cornerRadius
self.cpkAutoRoundingRadius = false
} else {
@ -213,7 +213,9 @@ public extension UIView {
* Usages:
.pin(.x(20)) //add left constraint
.pin(.x("20")) //add left margin constraint
.pin(.y(20)) //add top constraint
.pin(.y("20")) //add top margin constraint
.pin(.xy(20, 20)) //and left and top constraints
.pin(.w(100)) //add width constraint
@ -223,7 +225,9 @@ public extension UIView {
.pin(.xywh(20, 20, 100, 100)) //add left, top, width and height constraints
.pin(.maxX(-20)) //add right constraint
.pin(.maxX(-20)) //add right margin constraint
.pin(.maxY(-20)) //add bottom constraint
.pin(.maxY(-20)) //add bottom margin constraint
.pin(.maxXY(-20, -20)) //add right and bottom constraints
.pin(.centerX(0)) //add centerX constriant
@ -296,6 +300,11 @@ public extension UIView {
.embedIn(superview, 10, 20, 30) //top: 10, left: 20, right: 30
.embedIn(superview, 10, 20, 30, 40) //top: 10, left: 20, bottom: 30, right: 40
.embedIn(superview, 10, 20, nil) //top: 10, left: 20
* Passing string value instead of CGFloat will constraint to superview's margin.
* This is useful when embed in controller's view whose margin may not be 0.
* Usages:
.embedIn(superview, "10", 20, "30", 40) //topMargin: 10, left: 20, bottomMargin: 30, right: 40
*/
@discardableResult public func embedIn(_ superview: UIView,
_ p1: Any? = "", _ p2: Any? = "",
@ -306,16 +315,32 @@ public extension UIView {
makeCons({
if let top = edge.0 {
$0.top.offset(top)
if let topValue = top as? CGFloat {
$0.top.offset(topValue)
} else if let topMarginValue = CPKFloatOptional(top) {
$0.top.equal(superview).topMargin.offset(topMarginValue)
}
}
if let left = edge.1 {
$0.left.offset(left)
if let leftValue = left as? CGFloat {
$0.left.offset(leftValue)
} else if let leftMarginValue = CPKFloatOptional(left) {
$0.left.equal(superview).leftMargin.offset(leftMarginValue)
}
}
if let bottom = edge.2 {
$0.bottom.offset(-bottom)
if let bottomValue = bottom as? CGFloat {
$0.bottom.offset(-bottomValue)
} else if let bottomMarginValue = CPKFloatOptional(bottom) {
$0.bottom.equal(superview).bottomMargin.offset(-bottomMarginValue)
}
}
if let right = edge.3 {
$0.right.offset(-right)
if let rightValue = right as? CGFloat {
$0.right.offset(-rightValue)
} else if let rightMarginValue = CPKFloatOptional(right) {
$0.right.equal(superview).rightMargin.offset(-rightMarginValue)
}
}
})
@ -325,9 +350,9 @@ public extension UIView {
public enum CPKViewPinOptions {
case x(CGFloat) //left constraint
case y(CGFloat) //top constraint
case xy(CGFloat, CGFloat) //left and top constraints
case x(Any) //passing value for left constraint, passing string value for left margin constraint
case y(Any) //passing value for top constraint, passing string value for top margin constraint
case xy(Any, Any) //x + y
case w(CGFloat) //width constraint
case h(CGFloat) //height constraint
@ -336,9 +361,9 @@ public enum CPKViewPinOptions {
case xywh(CGFloat, CGFloat, //left, top, width and height constraints
CGFloat, CGFloat)
case maxX(CGFloat) //right constraint
case maxY(CGFloat) //bottom constraint
case maxXY(CGFloat, CGFloat) //right and bottom constraint
case maxX(Any) //passing value for right constraint, passing string value for right margin constraint
case maxY(Any) //passing value for bottom constraint, passing string value for bottom margin constraint
case maxXY(Any, Any) //maxX + maxY
case centerX(CGFloat) //centerX constraint
case centerY(CGFloat) //centerY constraint

View File

@ -76,6 +76,15 @@ func CPKFloatOptional(_ any: Any?) -> CGFloat? {
}
}
func CPKStringValueOptional(_ any: Any?) -> CGFloat? {
if let str = any as? String {
let f = Float(str)
return f != nil ? CGFloat(f!) : nil
} else {
return nil
}
}
func cpk_onePointImageWithColor(_ color: UIColor) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
let hasAlpha = cpk_colorHasAlphaChannel(color)
@ -150,46 +159,46 @@ func cpk_edgeInsetsTupleFromParameters(_ p1: Any? = "",
_ p3: Any? = "",
_ p4: Any? = "")
-> (CGFloat?, CGFloat?, CGFloat?, CGFloat?) {
-> (Any?, Any?, Any?, Any?) {
var leftOffset: CGFloat?
var rightOffset: CGFloat?
var topOffset: CGFloat?
var bottomOffset: CGFloat?
var leftOffset: Any?
var rightOffset: Any?
var topOffset: Any?
var bottomOffset: Any?
let isValidP1 = !(p1 is String)
let isValidP2 = !(p2 is String)
let isValidP3 = !(p3 is String)
let isValidP4 = !(p4 is String)
let isValidP1 = !(p1 is String) || ((p1 as! String) != "")
let isValidP2 = !(p2 is String) || ((p2 as! String) != "")
let isValidP3 = !(p3 is String) || ((p3 as! String) != "")
let isValidP4 = !(p4 is String) || ((p4 as! String) != "")
if isValidP1 && isValidP2 && isValidP3 && isValidP4 {
topOffset = CPKFloatOptional(p1)
leftOffset = CPKFloatOptional(p2)
bottomOffset = CPKFloatOptional(p3)
rightOffset = CPKFloatOptional(p4)
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
leftOffset = (p2 is String) ? p2 : CPKFloatOptional(p2)
bottomOffset = (p3 is String) ? p3 : CPKFloatOptional(p3)
rightOffset = (p4 is String) ? p4 : CPKFloatOptional(p4)
} else if isValidP1 && isValidP2 && isValidP3 {
topOffset = CPKFloatOptional(p1)
leftOffset = CPKFloatOptional(p2)
rightOffset = CPKFloatOptional(p3)
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
leftOffset = (p2 is String) ? p2 : CPKFloatOptional(p2)
rightOffset = (p3 is String) ? p3 : CPKFloatOptional(p3)
} else if isValidP1 && isValidP2 {
topOffset = CPKFloatOptional(p1)
leftOffset = CPKFloatOptional(p2)
bottomOffset = CPKFloatOptional(p1)
rightOffset = CPKFloatOptional(p2)
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
leftOffset = (p2 is String) ? p2 : CPKFloatOptional(p2)
bottomOffset = topOffset
rightOffset = leftOffset
} else if isValidP1 {
topOffset = CPKFloatOptional(p1)
leftOffset = CPKFloatOptional(p1)
bottomOffset = CPKFloatOptional(p1)
rightOffset = CPKFloatOptional(p1)
topOffset = (p1 is String) ? p1 : CPKFloatOptional(p1)
leftOffset = topOffset
bottomOffset = topOffset
rightOffset = topOffset
} else {
topOffset = 0
leftOffset = 0
bottomOffset = 0
rightOffset = 0
topOffset = CGFloat(0)
leftOffset = CGFloat(0)
bottomOffset = CGFloat(0)
rightOffset = CGFloat(0)
}
return (topOffset, leftOffset, bottomOffset, rightOffset)
@ -312,30 +321,94 @@ func cpk_updatePadding(_ padding: [CGFloat], forView view: UIView) {
func cpk_pinOptions(_ options: [CPKViewPinOptions], forView view: UIView) {
view.makeCons({
var values = [CGFloat]()
let priority: UILayoutPriority = 999
for option in options {
switch option {
case let .x(offset): $0.left.equal(offset)
case let .y(offset): $0.top.equal(offset)
case let .w(value): $0.width.equal(value)
case let .h(value): $0.height.equal(value)
case let .x(offset):
if let value = CPKStringValueOptional(offset) {
$0.left.equal("superview").leftMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(offset) {
$0.left.equal(value).priority(priority)
}
case let .xy(v1, v2): $0.left.top.equal(v1, v2); view.frame.origin = CGPoint(x: v1, y: v2)
case let .wh(v1, v2): $0.width.height.equal(v1, v2); view.frame.size = CGSize(width: v1, height: v2)
case let .xywh(v1, v2, v3, v4): $0.left.top.width.height.equal(v1, v2, v3, v4)
case let .y(offset):
if let value = CPKStringValueOptional(offset) {
$0.top.equal("superview").topMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(offset) {
$0.top.equal(value).priority(priority)
}
case let .maxX(offset): $0.right.equal(offset)
case let .maxY(offset): $0.bottom.equal(offset)
case let .maxXY(v1, v2): $0.right.bottom.equal(v1, v2)
case let .w(value):
view.frame.size.width = value
$0.width.equal(value).priority(priority)
case let .centerX(offset): $0.centerX.equal(offset)
case let .centerY(offset): $0.centerY.equal(offset)
case let .centerXY(v1, v2): $0.center.equal(v1, v2)
case let .h(value):
view.frame.size.height = value
$0.height.equal(value).priority(priority)
case let .xy(v1, v2):
if let value = CPKStringValueOptional(v1) {
$0.left.equal("superview").leftMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(v1) {
$0.left.equal(value).priority(priority)
}
if let value = CPKStringValueOptional(v2) {
$0.top.equal("superview").topMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(v2) {
$0.top.equal(value).priority(priority)
}
case let .wh(v1, v2):
view.frame.size = CGSize(width: v1, height: v2)
$0.width.height.equal(v1, v2).priority(priority)
case let .xywh(v1, v2, v3, v4):
view.frame = CGRect(x: v1, y: v2, width: v3, height: v4)
$0.left.top.width.height.equal(v1, v2, v3, v4).priority(priority);
case let .maxX(offset):
if let value = CPKStringValueOptional(offset) {
$0.right.equal("superview").rightMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(offset) {
$0.right.equal(value).priority(priority)
}
case let .maxY(offset):
if let value = CPKStringValueOptional(offset) {
$0.bottom.equal("superview").bottomMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(offset) {
$0.bottom.equal(value).priority(priority)
}
case let .maxXY(v1, v2):
if let value = CPKStringValueOptional(v1) {
$0.right.equal("superview").rightMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(v1) {
$0.right.equal(value).priority(priority)
}
if let value = CPKStringValueOptional(v2) {
$0.bottom.equal("superview").bottomMargin.offset(value).priority(priority)
} else if let value = CPKFloatOptional(v2) {
$0.bottom.equal(value).priority(priority)
}
case let .centerX(offset):
$0.centerX.equal(offset)
case let .centerY(offset):
$0.centerY.equal(offset)
case let .centerXY(v1, v2):
$0.center.equal(v1, v2)
case let .whRatio(ratio): $0.width.equal(view).height.multiply(ratio)
case .center: $0.center.equal(0)
case .ratio: $0.width.equal(view).height.multiply(view.frame.width / view.frame.height)
case .center:
$0.center.equal(0)
case .ratio:
$0.width.equal(view).height.multiply(view.frame.width / view.frame.height)
case let .hhp(value): view.setContentHuggingPriority(value, for: .horizontal)
case let .vhp(value): view.setContentHuggingPriority(value, for: .vertical)
@ -350,16 +423,20 @@ func cpk_pinOptions(_ options: [CPKViewPinOptions], forView view: UIView) {
view.setContentCompressionResistancePriority(kLowPriority, for: .horizontal)
view.setContentCompressionResistancePriority(kLowPriority, for: .vertical)
case let .___value(value): values.append(value)
case let .___value(value):
values.append(value)
}
}
if values.count == 1 {
$0.height.equal(values[0])
view.frame.size.height = values[0]
$0.height.equal(values[0]).priority(priority)
} else if values.count == 2 {
$0.size.equal(values[0], values[1])
view.frame.size = CGSize(width: values[0], height: values[1])
$0.size.equal(values[0], values[1]).priority(priority)
} else if values.count == 4 {
$0.origin.size.equal(values[0], values[1], values[2], values[3])
view.frame = CGRect(x: values[0], y: values[1], width: values[2], height: values[3])
$0.origin.size.equal(values[0], values[1], values[2], values[3]).priority(priority)
}
})
}
@ -1029,6 +1106,7 @@ public class ConsAtts: NSObject {
public class Cons: ConsAtts {
private let firstItem: UIView
private var secondItem: UIView?
private var secondItemReferToSuperview = false
var relation = NSLayoutRelation.equal
@ -1050,7 +1128,7 @@ public class Cons: ConsAtts {
@discardableResult
override func addAttributes(_ attributes: NSLayoutAttribute...) -> Cons {
for att in attributes {
if secondItem == nil {
if secondItem == nil && !secondItemReferToSuperview {
firstItemAttributes.append(att)
} else {
secondItemAttributes.append(att)
@ -1066,6 +1144,9 @@ public class Cons: ConsAtts {
} else if let item2 = item2OrValues.first as? String {
if item2 == "self" {
self.secondItem = self.firstItem
} else if item2 == "superview" {
self.secondItem = nil
self.secondItemReferToSuperview = true
} else {
assert(false, "invalid second item")
}
@ -1582,6 +1663,8 @@ public class StaticTableView: UITableView, UITableViewDelegate, UITableViewDataS
public init(sectionsOrRows: [Any], style: UITableViewStyle) {
super.init(frame: CGRect.zero, style: style)
self.estimatedRowHeight = 44
self.estimatedSectionHeaderHeight = 0
self.estimatedSectionFooterHeight = 0
self.delegate = self
self.dataSource = self
updateSections(sectionsOrRows: sectionsOrRows)