Repository: DavdRoman/Popsicle
Branch: master
Commit: 11c714218bbd
Files: 27
Total size: 79.7 KB
Directory structure:
gitextract_ps5q6ues/
├── .gitignore
├── LICENSE
├── Popsicle/
│ ├── EasingFunction.swift
│ ├── Info.plist
│ ├── Interpolable.swift
│ ├── Interpolation.swift
│ ├── Interpolator.swift
│ ├── KeyPath.swift
│ └── Popsicle.h
├── Popsicle.podspec
├── Popsicle.xcodeproj/
│ ├── project.pbxproj
│ ├── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── xcshareddata/
│ └── xcschemes/
│ └── Popsicle.xcscheme
├── PopsicleDemo/
│ ├── AppDelegate.swift
│ ├── Assets.xcassets/
│ │ ├── AppIcon.appiconset/
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── logo.imageset/
│ │ └── Contents.json
│ ├── Base.lproj/
│ │ └── LaunchScreen.storyboard
│ ├── DRPageScrollView.h
│ ├── DRPageScrollView.m
│ ├── Info.plist
│ ├── PageScrollView.swift
│ ├── PageViews.xib
│ ├── PopsicleDemo-Bridging-Header.h
│ ├── UIView+Utils.swift
│ └── ViewController.swift
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# OS X
.DS_Store
# Xcode
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 IFTTT Inc
Copyright (c) 2015 David Román
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.
================================================
FILE: Popsicle/EasingFunction.swift
================================================
//
// EasingFunction.swift
// RazzleDazzle
//
// Created by Laura Skelton on 6/15/15.
// Copyright (c) 2015 IFTTT. All rights reserved.
//
// Ported to Swift from Robert Böhnke's RBBAnimation, original available here:
// <https://github.com/robb/RBBAnimation/blob/a29cafe2fa91e62573cc9967990b0ad2a6b17a76/RBBAnimation/RBBEasingFunction.m>
public typealias EasingFunction = (Progress) -> (Progress)
public let EasingFunctionLinear: EasingFunction = { t in
return t
}
public let EasingFunctionEaseInQuad: EasingFunction = { t in
return t * t
}
public let EasingFunctionEaseOutQuad: EasingFunction = { t in
return t * (2 - t)
}
public let EasingFunctionEaseInOutQuad: EasingFunction = { t in
if (t < 0.5) { return 2 * t * t }
return -1 + ((4 - (2 * t)) * t)
}
public let EasingFunctionEaseInCubic: EasingFunction = { t in
return t * t * t
}
public let EasingFunctionEaseOutCubic: EasingFunction = { t in
return pow(t - 1, 3) + 1
}
public let EasingFunctionEaseInOutCubic: EasingFunction = { t in
if (t < 0.5) { return 4 * pow(t, 3) }
return ((t - 1) * pow((2 * t) - 2, 2)) + 1
}
public let EasingFunctionEaseInBounce: EasingFunction = { t in
return 1 - EasingFunctionEaseOutBounce(1 - t)
}
public let EasingFunctionEaseOutBounce: EasingFunction = { t in
if (t < (4.0 / 11.0)) {
return pow((11.0 / 4.0), 2) * pow(t, 2)
}
if (t < (8.0 / 11.0)) {
return (3.0 / 4.0) + (pow((11.0 / 4.0), 2) * pow(t - (6.0 / 11.0), 2))
}
if (t < (10.0 / 11.0)) {
return (15.0 / 16.0) + (pow((11.0 / 4.0), 2) * pow(t - (9.0 / 11.0), 2))
}
return (63.0 / 64.0) + (pow((11.0 / 4.0), 2) * pow(t - (21.0 / 22.0), 2))
}
================================================
FILE: Popsicle/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
================================================
FILE: Popsicle/Interpolable.swift
================================================
//
// Interpolable.swift
// Popsicle
//
// Created by David Román Aguirre on 01/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
/// A value from 0 to 1 defining the progress of a certain interpolation between two `Interpolable` values.
public typealias Progress = Double
/// Defines a common protocol for all interpolable values.
///
/// Types conforming to this protocol are available to use as a `Interpolation` generic type.
public protocol Interpolable {
typealias ValueType
/// Defines how an interpolation should be performed between two given values of the type conforming to this protocol.
static func interpolate(from fromValue: ValueType, to toValue: ValueType, withProgress: Progress) -> ValueType
/// Converts a value to a valid `Foundation` object, if necessary.
static func objectify(value: ValueType) -> AnyObject
}
extension Bool: Interpolable {
public static func interpolate(from fromValue: Bool, to toValue: Bool, withProgress progress: Progress) -> Bool {
return progress >= 0.5 ? toValue : fromValue
}
public static func objectify(value: Bool) -> AnyObject {
return NSNumber(bool: value)
}
}
extension CGFloat: Interpolable {
public static func interpolate(from fromValue: CGFloat, to toValue: CGFloat, withProgress progress: Progress) -> CGFloat {
return fromValue+(toValue-fromValue)*CGFloat(progress)
}
public static func objectify(value: CGFloat) -> AnyObject {
return NSNumber(double: Double(value))
}
}
extension CGPoint: Interpolable {
public static func interpolate(from fromValue: CGPoint, to toValue: CGPoint, withProgress progress: Progress) -> CGPoint {
let x = CGFloat.interpolate(from: fromValue.x, to: toValue.x, withProgress: progress)
let y = CGFloat.interpolate(from: fromValue.y, to: toValue.y, withProgress: progress)
return CGPointMake(x, y)
}
public static func objectify(value: CGPoint) -> AnyObject {
return NSValue(CGPoint: value)
}
}
extension CGSize: Interpolable {
public static func interpolate(from fromValue: CGSize, to toValue: CGSize, withProgress progress: Progress) -> CGSize {
let width = CGFloat.interpolate(from: fromValue.width, to: toValue.width, withProgress: progress)
let height = CGFloat.interpolate(from: fromValue.height, to: toValue.height, withProgress: progress)
return CGSizeMake(width, height)
}
public static func objectify(value: CGSize) -> AnyObject {
return NSValue(CGSize: value)
}
}
extension CGRect: Interpolable {
public static func interpolate(from fromValue: CGRect, to toValue: CGRect, withProgress progress: Progress) -> CGRect {
let origin = CGPoint.interpolate(from: fromValue.origin, to: toValue.origin, withProgress: progress)
let size = CGSize.interpolate(from: fromValue.size, to: toValue.size, withProgress: progress)
return CGRectMake(origin.x, origin.y, size.width, size.height)
}
public static func objectify(value: CGRect) -> AnyObject {
return NSValue(CGRect: value)
}
}
extension CGAffineTransform: Interpolable {
public static func interpolate(from fromValue: CGAffineTransform, to toValue: CGAffineTransform, withProgress progress: Progress) -> CGAffineTransform {
let tx1 = CGAffineTransformGetTranslationX(fromValue)
let tx2 = CGAffineTransformGetTranslationX(toValue)
let tx = CGFloat.interpolate(from: tx1, to: tx2, withProgress: progress)
let ty1 = CGAffineTransformGetTranslationY(fromValue)
let ty2 = CGAffineTransformGetTranslationY(toValue)
let ty = CGFloat.interpolate(from: ty1, to: ty2, withProgress: progress)
let sx1 = CGAffineTransformGetScaleX(fromValue)
let sx2 = CGAffineTransformGetScaleX(toValue)
let sx = CGFloat.interpolate(from: sx1, to: sx2, withProgress: progress)
let sy1 = CGAffineTransformGetScaleY(fromValue)
let sy2 = CGAffineTransformGetScaleY(toValue)
let sy = CGFloat.interpolate(from: sy1, to: sy2, withProgress: progress)
let deg1 = CGAffineTransformGetRotation(fromValue)
let deg2 = CGAffineTransformGetRotation(toValue)
let deg = CGFloat.interpolate(from: deg1, to: deg2, withProgress: progress)
return CGAffineTransformMake(tx, ty, sx, sy, deg)
}
public static func objectify(value: CGAffineTransform) -> AnyObject {
return NSValue(CGAffineTransform: value)
}
}
/// `CGAffineTransformMake()`, The Right Way™
///
/// - parameter tx: translation on x axis.
/// - parameter ty: translation on y axis.
/// - parameter sx: scale factor for width.
/// - parameter sy: scale factor for height.
/// - parameter deg: degrees.
public func CGAffineTransformMake(tx: CGFloat, _ ty: CGFloat, _ sx: CGFloat, _ sy: CGFloat, _ deg: CGFloat) -> CGAffineTransform {
let translationTransform = CGAffineTransformMakeTranslation(tx, ty)
let scaleTransform = CGAffineTransformMakeScale(sx, sy)
let rotationTransform = CGAffineTransformMakeRotation(deg*CGFloat(M_PI_2)/180)
return CGAffineTransformConcat(CGAffineTransformConcat(translationTransform, scaleTransform), rotationTransform)
}
func CGAffineTransformGetTranslationX(t: CGAffineTransform) -> CGFloat { return t.tx }
func CGAffineTransformGetTranslationY(t: CGAffineTransform) -> CGFloat { return t.ty }
func CGAffineTransformGetScaleX(t: CGAffineTransform) -> CGFloat { return sqrt(t.a * t.a + t.c * t.c) }
func CGAffineTransformGetScaleY(t: CGAffineTransform) -> CGFloat { return sqrt(t.b * t.b + t.d * t.d) }
func CGAffineTransformGetRotation(t: CGAffineTransform) -> CGFloat { return (atan2(t.b, t.a)*180)/CGFloat(M_PI_2) }
extension UIColor: Interpolable {
public static func interpolate(from fromValue: UIColor, to toValue: UIColor, withProgress progress: Progress) -> UIColor {
var fromRed: CGFloat = 0
var fromGreen: CGFloat = 0
var fromBlue: CGFloat = 0
var fromAlpha: CGFloat = 0
var toRed: CGFloat = 0
var toGreen: CGFloat = 0
var toBlue: CGFloat = 0
var toAlpha: CGFloat = 0
fromValue.getRed(&fromRed, green: &fromGreen, blue: &fromBlue, alpha: &fromAlpha)
toValue.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha)
let red = CGFloat.interpolate(from: fromRed, to: toRed, withProgress: progress)
let green = CGFloat.interpolate(from: fromGreen, to: toGreen, withProgress: progress)
let blue = CGFloat.interpolate(from: fromBlue, to: toBlue, withProgress: progress)
let alpha = CGFloat.interpolate(from: fromAlpha, to: toAlpha, withProgress: progress)
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
}
public static func objectify(value: UIColor) -> AnyObject {
return value
}
}
================================================
FILE: Popsicle/Interpolation.swift
================================================
//
// Interpolation.swift
// Popsicle
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
protocol ObjectReferable {
var objectReference: NSObject { get }
}
protocol Timeable {
func setTime(time: Time)
}
/// `Interpolation` defines an interpolation which changes some `NSObject` value given by a key path.
public class Interpolation<T: Interpolable> : Equatable, ObjectReferable, Timeable {
let object: NSObject
let keyPath: String
let originalObject: NSObject
var objectReference: NSObject { return self.originalObject }
typealias Pole = (T.ValueType, EasingFunction)
private var poles: [Time: Pole] = [:]
public init<U: NSObject>(_ object: U, _ keyPath: KeyPath<U, T>) {
self.originalObject = object
(self.object, self.keyPath) = NSObject.filteredObjectAndKeyPath(withObject: object, andKeyPath: keyPath)
if !self.object.respondsToSelector(NSSelectorFromString(self.keyPath)) {
assertionFailure("Please make sure the key path \"" + self.keyPath + "\" you're referring to for an object of type <" + NSStringFromClass(self.object.dynamicType) + "> is invalid")
}
}
/// A convenience initializer with `keyPath` as a `String` parameter. You should try to avoid this method unless absolutely necessary, due to its unsafety.
public convenience init(_ object: NSObject, _ keyPath: String) {
self.init(object, KeyPath(keyPathable: keyPath))
}
/// Sets a specific easing function for the interpolation to be performed with for a given time.
///
/// - parameter easingFunction: the easing function to use.
/// - parameter time: the time where the easing function should be used.
public func setEasingFunction(easingFunction: EasingFunction, forTime time: Time) {
self.poles[time]?.1 = easingFunction
}
public subscript(time1: Time, rest: Time...) -> T.ValueType? {
get {
assert(poles.count >= 2, "You must specify at least 2 poles for an interpolation to be performed")
if let existingPole = poles[time1] {
return existingPole.0
} else if let timeInterval = poles.keys.sort().elementsAround(time1) {
guard let fromTime = timeInterval.0 else {
return poles[timeInterval.1!]!.0
}
guard let toTime = timeInterval.1 else {
return poles[timeInterval.0!]!.0
}
let easingFunction = poles[fromTime]!.1
let progress = easingFunction(self.progress(fromTime, toTime, time1))
return T.interpolate(from: poles[fromTime]!.0, to: poles[toTime]!.0, withProgress: progress)
}
return nil
}
set {
var times = [time1]
times.appendContentsOf(rest)
for time in times {
poles[time] = (newValue!, EasingFunctionLinear)
}
}
}
func progress(fromTime: Time, _ toTime: Time, _ currentTime: Time) -> Progress {
let p = (currentTime-fromTime)/(toTime-fromTime)
return min(1, max(0, p))
}
func setTime(time: Time) {
self.object.setValue(T.objectify(self[time]!), forKeyPath: self.keyPath)
}
}
public func ==<T: Interpolable>(lhs: Interpolation<T>, rhs: Interpolation<T>) -> Bool {
return lhs.object == rhs.object && lhs.keyPath == rhs.keyPath
}
extension Array where Element: Comparable {
func elementPairs() -> [(Element, Element)]? {
if self.count >= 2 {
var elementPairs: [(Element, Element)] = []
for (i, e) in self.sort().enumerate() {
if i+1 < self.count {
elementPairs.append((e, self[i+1]))
}
}
return elementPairs
}
return nil
}
func elementsAround(element: Element) -> (Element?, Element?)? {
if let pairs = self.elementPairs() {
let minElement = pairs.first!.0
let maxElement = pairs.last!.1
if element < minElement {
return (nil, minElement)
}
if element > maxElement {
return (maxElement, nil)
}
for (e1, e2) in pairs where (e1...e2).contains(element) {
return (e1, e2)
}
}
return nil
}
}
================================================
FILE: Popsicle/Interpolator.swift
================================================
//
// Interpolator.swift
// Popsicle
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
/// Value type on which interpolation values rely on.
public typealias Time = Double
/// `Interpolator` collects and coordinates a set of related interpolations through its `time` property.
public class Interpolator {
var interpolations = [Timeable]()
public init() {}
public func addInterpolation<T: Interpolable>(interpolation: Interpolation<T>) {
self.interpolations.append(interpolation)
}
public var time: Time = 0 {
didSet {
self.interpolations.forEach { $0.setTime(self.time) }
}
}
public func removeInterpolation<T: Interpolable>(interpolation: Interpolation<T>) {
for (index, element) in self.interpolations.enumerate() {
if let interpolation = element as? Interpolation<T> {
if interpolation == interpolation {
self.interpolations.removeAtIndex(index)
}
}
}
}
/// Removes all interpolations containing the specified object.
public func removeInterpolations(forObject object: NSObject) {
for (index, element) in self.interpolations.enumerate() {
if let interpolation = element as? ObjectReferable {
if interpolation.objectReference == object {
self.interpolations.removeAtIndex(index)
self.removeInterpolations(forObject: object) // Recursivity FTW
return
}
}
}
}
public func removeAllInterpolations() {
self.interpolations.removeAll()
}
}
================================================
FILE: Popsicle/KeyPath.swift
================================================
//
// KeyPath.swift
// Popsicle
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
/// `KeyPathable` defines how a value is transformed to a valid `NSObject` key path.
public protocol KeyPathable {
func stringify() -> String
}
extension String : KeyPathable {
public func stringify() -> String {
return self
}
}
extension NSLayoutAttribute: KeyPathable {
public func stringify() -> String {
var type = "UnknownAttribute"
switch(self) {
case .Left:
type = "Left"
case .Right:
type = "Right"
case .Top:
type = "Top"
case .Bottom:
type = "Bottom"
case .Leading:
type = "Leading"
case .Trailing:
type = "Trailing"
case .Width:
type = "Width"
case .Height:
type = "Height"
case .CenterX:
type = "CenterX"
case .CenterY:
type = "CenterY"
case .LastBaseline:
type = "Baseline"
case .FirstBaseline:
type = "FirstBaseline"
case .LeftMargin:
type = "LeftMargin"
case .RightMargin:
type = "RightMargin"
case .TopMargin:
type = "TopMargin"
case .BottomMargin:
type = "BottomMargin"
case .LeadingMargin:
type = "LeadingMargin"
case .TrailingMargin:
type = "TrailingMargin"
case .CenterXWithinMargins:
type = "CenterXWithinMargins"
case .CenterYWithinMargins:
type = "CenterYWithinMargins"
case .NotAnAttribute:
type = "NotAnAttribute"
}
return "NSLayoutAttribute." + type
}
}
/// `KeyPath` defines a `NSObject`'s key path, constrained to specific `NSObject` and `Interpolable` types for higher safety.
public struct KeyPath<T: NSObject, U: Interpolable> {
let keyPathable: KeyPathable
public init(keyPathable: KeyPathable) {
self.keyPathable = keyPathable
}
}
public let alpha = KeyPath<UIView, CGFloat>(keyPathable: "alpha")
public let backgroundColor = KeyPath<UIView, UIColor>(keyPathable: "backgroundColor")
public let barTintColor = KeyPath<UIView, UIColor>(keyPathable: "barTintColor")
public let borderColor = KeyPath<CALayer, CGFloat>(keyPathable: "borderColor")
public let borderWidth = KeyPath<CALayer, CGFloat>(keyPathable: "borderWidth")
public let constant = KeyPath<NSLayoutConstraint, CGFloat>(keyPathable: "constant")
public let cornerRadius = KeyPath<CALayer, CGFloat>(keyPathable: "cornerRadius")
public let hidden = KeyPath<UIView, Bool>(keyPathable: "hidden")
public let textColor = KeyPath<UIView, UIColor>(keyPathable: "textColor")
public let tintColor = KeyPath<UIView, UIColor>(keyPathable: "tintColor")
public let transform = KeyPath<UIView, CGAffineTransform>(keyPathable: "transform")
public let baselineConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.LastBaseline)
public let firstBaselineConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.FirstBaseline)
public let topConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Top)
public let leftConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Left)
public let rightConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Right)
public let bottomConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Bottom)
public let leadingConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Leading)
public let trailingConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Trailing)
public let leftMarginConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.LeftMargin)
public let rightMarginConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.RightMargin)
public let topMarginConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.TopMargin)
public let bottomMarginConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.BottomMargin)
public let leadingMarginConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.LeadingMargin)
public let trailingMarginConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.TrailingMargin)
public let centerXConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.CenterX)
public let centerYConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.CenterY)
public let centerXWithinMarginsConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.CenterXWithinMargins)
public let centerYWithinMarginsConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.CenterYWithinMargins)
public let widthConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Width)
public let heightConstraint = KeyPath<UIView, CGFloat>(keyPathable: NSLayoutAttribute.Height)
extension NSObject {
static func filteredObjectAndKeyPath<T: NSObject, U: Interpolable>(withObject object: T, andKeyPath keyPath: KeyPath<T, U>) -> (NSObject, String) {
if let view = object as? UIView, let superview = view.superview, let attribute = keyPath.keyPathable as? NSLayoutAttribute {
let constrainedView = (attribute == .Width || attribute == .Height) ? view : superview
for constraint in constrainedView.constraints where
!constraint.isKindOfClass(NSClassFromString("NSContentSizeLayoutConstraint")!) &&
((constraint.firstItem as? NSObject == view && constraint.firstAttribute == attribute) ||
(constraint.secondItem as? NSObject == view && constraint.secondAttribute == attribute)) {
return (constraint, constant.keyPathable.stringify())
}
}
return (object, keyPath.keyPathable.stringify())
}
}
================================================
FILE: Popsicle/Popsicle.h
================================================
//
// Popsicle.h
// Popsicle
//
// Created by David Román Aguirre on 01/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
@import UIKit;
//! Project version number for Popsicle.
FOUNDATION_EXPORT double PopsicleVersionNumber;
//! Project version string for Popsicle.
FOUNDATION_EXPORT const unsigned char PopsicleVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <Popsicle/PublicHeader.h>
================================================
FILE: Popsicle.podspec
================================================
Pod::Spec.new do |s|
s.name = "Popsicle"
s.version = "2.0.1"
s.summary = "Delightful, extensible Swift value interpolation framework"
s.homepage = "https://github.com/DavdRoman/Popsicle"
s.author = { "David Román" => "d@vidroman.me" }
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.social_media_url = 'https://twitter.com/DavdRoman'
s.platform = :ios, '8.0'
s.ios.deployment_target = '8.0'
s.source = { :git => "https://github.com/DavdRoman/Popsicle.git", :tag => s.version.to_s }
s.source_files = 'Popsicle/*.{h,swift}'
s.frameworks = 'UIKit'
s.requires_arc = true
end
================================================
FILE: Popsicle.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
D53B324C1BE65FF800A1820B /* Interpolable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53B324B1BE65FF800A1820B /* Interpolable.swift */; };
D53E5FD91BEA12340043DF84 /* EasingFunction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FD81BEA12340043DF84 /* EasingFunction.swift */; };
D53E5FDB1BEA13600043DF84 /* Interpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FDA1BEA13600043DF84 /* Interpolation.swift */; };
D53E5FDD1BEA13900043DF84 /* Interpolator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FDC1BEA13900043DF84 /* Interpolator.swift */; };
D53E5FE51BEA145F0043DF84 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FE41BEA145F0043DF84 /* AppDelegate.swift */; };
D53E5FE71BEA145F0043DF84 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FE61BEA145F0043DF84 /* ViewController.swift */; };
D53E5FEC1BEA145F0043DF84 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D53E5FEB1BEA145F0043DF84 /* Assets.xcassets */; };
D53E5FEF1BEA145F0043DF84 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D53E5FED1BEA145F0043DF84 /* LaunchScreen.storyboard */; };
D53E5FF71BEA16D70043DF84 /* PageViews.xib in Resources */ = {isa = PBXBuildFile; fileRef = D53E5FF61BEA16D70043DF84 /* PageViews.xib */; };
D53E60011BEA203B0043DF84 /* PageScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FFF1BEA199C0043DF84 /* PageScrollView.swift */; };
D53E60021BEA227D0043DF84 /* DRPageScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = D53E5FFA1BEA18140043DF84 /* DRPageScrollView.m */; };
D53E60051BEA67790043DF84 /* UIView+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53E60041BEA67790043DF84 /* UIView+Utils.swift */; };
D593A8DD1BEA72E500AFA257 /* Popsicle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5FBF53A1BE65BB500F3CB79 /* Popsicle.framework */; };
D593A8DE1BEA72E500AFA257 /* Popsicle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D5FBF53A1BE65BB500F3CB79 /* Popsicle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D5D6A94C1BEBB85A008E414E /* KeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = D593A8E41BEA88B600AFA257 /* KeyPath.swift */; };
D5FBF53E1BE65BB500F3CB79 /* Popsicle.h in Headers */ = {isa = PBXBuildFile; fileRef = D5FBF53D1BE65BB500F3CB79 /* Popsicle.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
D593A8DF1BEA72E500AFA257 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D5FBF5311BE65BB500F3CB79 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D5FBF5391BE65BB500F3CB79;
remoteInfo = Popsicle;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
D593A8E11BEA72E500AFA257 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
D593A8DE1BEA72E500AFA257 /* Popsicle.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
D53B324B1BE65FF800A1820B /* Interpolable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Interpolable.swift; sourceTree = "<group>"; };
D53E5FD81BEA12340043DF84 /* EasingFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingFunction.swift; sourceTree = "<group>"; };
D53E5FDA1BEA13600043DF84 /* Interpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Interpolation.swift; sourceTree = "<group>"; };
D53E5FDC1BEA13900043DF84 /* Interpolator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Interpolator.swift; sourceTree = "<group>"; };
D53E5FE21BEA145F0043DF84 /* PopsicleDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PopsicleDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
D53E5FE41BEA145F0043DF84 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
D53E5FE61BEA145F0043DF84 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
D53E5FEB1BEA145F0043DF84 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
D53E5FEE1BEA145F0043DF84 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
D53E5FF01BEA145F0043DF84 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D53E5FF61BEA16D70043DF84 /* PageViews.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PageViews.xib; sourceTree = "<group>"; };
D53E5FF81BEA18130043DF84 /* PopsicleDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PopsicleDemo-Bridging-Header.h"; sourceTree = "<group>"; };
D53E5FF91BEA18140043DF84 /* DRPageScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRPageScrollView.h; sourceTree = "<group>"; };
D53E5FFA1BEA18140043DF84 /* DRPageScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRPageScrollView.m; sourceTree = "<group>"; };
D53E5FFF1BEA199C0043DF84 /* PageScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PageScrollView.swift; sourceTree = "<group>"; };
D53E60041BEA67790043DF84 /* UIView+Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Utils.swift"; sourceTree = "<group>"; };
D593A8E41BEA88B600AFA257 /* KeyPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyPath.swift; sourceTree = "<group>"; };
D5FBF53A1BE65BB500F3CB79 /* Popsicle.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Popsicle.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D5FBF53D1BE65BB500F3CB79 /* Popsicle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Popsicle.h; sourceTree = "<group>"; };
D5FBF53F1BE65BB500F3CB79 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D53E5FDF1BEA145F0043DF84 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D593A8DD1BEA72E500AFA257 /* Popsicle.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D5FBF5361BE65BB500F3CB79 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
D516D8DF1D1A90910086E8E6 /* Supporting Files */ = {
isa = PBXGroup;
children = (
D53E5FEB1BEA145F0043DF84 /* Assets.xcassets */,
D53E5FED1BEA145F0043DF84 /* LaunchScreen.storyboard */,
D53E5FF01BEA145F0043DF84 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
D53E5FE31BEA145F0043DF84 /* PopsicleDemo */ = {
isa = PBXGroup;
children = (
D53E5FE41BEA145F0043DF84 /* AppDelegate.swift */,
D53E5FE61BEA145F0043DF84 /* ViewController.swift */,
D5F2E3E11BEB720B00008043 /* Page Scroll View */,
D516D8DF1D1A90910086E8E6 /* Supporting Files */,
);
path = PopsicleDemo;
sourceTree = "<group>";
};
D5F2E3E11BEB720B00008043 /* Page Scroll View */ = {
isa = PBXGroup;
children = (
D53E5FF81BEA18130043DF84 /* PopsicleDemo-Bridging-Header.h */,
D53E5FF91BEA18140043DF84 /* DRPageScrollView.h */,
D53E5FFA1BEA18140043DF84 /* DRPageScrollView.m */,
D53E5FFF1BEA199C0043DF84 /* PageScrollView.swift */,
D53E5FF61BEA16D70043DF84 /* PageViews.xib */,
D53E60041BEA67790043DF84 /* UIView+Utils.swift */,
);
name = "Page Scroll View";
sourceTree = "<group>";
};
D5FBF5301BE65BB500F3CB79 = {
isa = PBXGroup;
children = (
D53E5FE31BEA145F0043DF84 /* PopsicleDemo */,
D5FBF53C1BE65BB500F3CB79 /* Popsicle */,
D5FBF53B1BE65BB500F3CB79 /* Products */,
);
sourceTree = "<group>";
};
D5FBF53B1BE65BB500F3CB79 /* Products */ = {
isa = PBXGroup;
children = (
D5FBF53A1BE65BB500F3CB79 /* Popsicle.framework */,
D53E5FE21BEA145F0043DF84 /* PopsicleDemo.app */,
);
name = Products;
sourceTree = "<group>";
};
D5FBF53C1BE65BB500F3CB79 /* Popsicle */ = {
isa = PBXGroup;
children = (
D5FBF53D1BE65BB500F3CB79 /* Popsicle.h */,
D53E5FDC1BEA13900043DF84 /* Interpolator.swift */,
D53E5FDA1BEA13600043DF84 /* Interpolation.swift */,
D53B324B1BE65FF800A1820B /* Interpolable.swift */,
D53E5FD81BEA12340043DF84 /* EasingFunction.swift */,
D593A8E41BEA88B600AFA257 /* KeyPath.swift */,
D5FBF53F1BE65BB500F3CB79 /* Info.plist */,
);
path = Popsicle;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D5FBF5371BE65BB500F3CB79 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
D5FBF53E1BE65BB500F3CB79 /* Popsicle.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
D53E5FE11BEA145F0043DF84 /* PopsicleDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = D53E5FF11BEA145F0043DF84 /* Build configuration list for PBXNativeTarget "PopsicleDemo" */;
buildPhases = (
D53E5FDE1BEA145F0043DF84 /* Sources */,
D53E5FDF1BEA145F0043DF84 /* Frameworks */,
D53E5FE01BEA145F0043DF84 /* Resources */,
D593A8E11BEA72E500AFA257 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
D593A8E01BEA72E500AFA257 /* PBXTargetDependency */,
);
name = PopsicleDemo;
productName = PopsicleDemo;
productReference = D53E5FE21BEA145F0043DF84 /* PopsicleDemo.app */;
productType = "com.apple.product-type.application";
};
D5FBF5391BE65BB500F3CB79 /* Popsicle */ = {
isa = PBXNativeTarget;
buildConfigurationList = D5FBF54E1BE65BB600F3CB79 /* Build configuration list for PBXNativeTarget "Popsicle" */;
buildPhases = (
D5FBF5351BE65BB500F3CB79 /* Sources */,
D5FBF5361BE65BB500F3CB79 /* Frameworks */,
D5FBF5371BE65BB500F3CB79 /* Headers */,
D5FBF5381BE65BB500F3CB79 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Popsicle;
productName = Popsicle;
productReference = D5FBF53A1BE65BB500F3CB79 /* Popsicle.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D5FBF5311BE65BB500F3CB79 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = "David Román Aguirre";
TargetAttributes = {
D53E5FE11BEA145F0043DF84 = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 0800;
};
D5FBF5391BE65BB500F3CB79 = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 0800;
};
};
};
buildConfigurationList = D5FBF5341BE65BB500F3CB79 /* Build configuration list for PBXProject "Popsicle" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = D5FBF5301BE65BB500F3CB79;
productRefGroup = D5FBF53B1BE65BB500F3CB79 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D53E5FE11BEA145F0043DF84 /* PopsicleDemo */,
D5FBF5391BE65BB500F3CB79 /* Popsicle */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D53E5FE01BEA145F0043DF84 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D53E5FEF1BEA145F0043DF84 /* LaunchScreen.storyboard in Resources */,
D53E5FEC1BEA145F0043DF84 /* Assets.xcassets in Resources */,
D53E5FF71BEA16D70043DF84 /* PageViews.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D5FBF5381BE65BB500F3CB79 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D53E5FDE1BEA145F0043DF84 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D53E5FE71BEA145F0043DF84 /* ViewController.swift in Sources */,
D53E5FE51BEA145F0043DF84 /* AppDelegate.swift in Sources */,
D53E60051BEA67790043DF84 /* UIView+Utils.swift in Sources */,
D53E60021BEA227D0043DF84 /* DRPageScrollView.m in Sources */,
D53E60011BEA203B0043DF84 /* PageScrollView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D5FBF5351BE65BB500F3CB79 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D53E5FDD1BEA13900043DF84 /* Interpolator.swift in Sources */,
D5D6A94C1BEBB85A008E414E /* KeyPath.swift in Sources */,
D53E5FD91BEA12340043DF84 /* EasingFunction.swift in Sources */,
D53B324C1BE65FF800A1820B /* Interpolable.swift in Sources */,
D53E5FDB1BEA13600043DF84 /* Interpolation.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
D593A8E01BEA72E500AFA257 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D5FBF5391BE65BB500F3CB79 /* Popsicle */;
targetProxy = D593A8DF1BEA72E500AFA257 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
D53E5FED1BEA145F0043DF84 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
D53E5FEE1BEA145F0043DF84 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
D53E5FF21BEA145F0043DF84 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = PopsicleDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = me.davidroman.PopsicleDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "PopsicleDemo/PopsicleDemo-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 2.3;
};
name = Debug;
};
D53E5FF31BEA145F0043DF84 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = PopsicleDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = me.davidroman.PopsicleDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "PopsicleDemo/PopsicleDemo-Bridging-Header.h";
SWIFT_VERSION = 2.3;
};
name = Release;
};
D5FBF54C1BE65BB600F3CB79 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
D5FBF54D1BE65BB600F3CB79 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
D5FBF54F1BE65BB600F3CB79 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Popsicle/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = me.davidroman.Popsicle;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 2.3;
};
name = Debug;
};
D5FBF5501BE65BB600F3CB79 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = Popsicle/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = me.davidroman.Popsicle;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 2.3;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D53E5FF11BEA145F0043DF84 /* Build configuration list for PBXNativeTarget "PopsicleDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D53E5FF21BEA145F0043DF84 /* Debug */,
D53E5FF31BEA145F0043DF84 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D5FBF5341BE65BB500F3CB79 /* Build configuration list for PBXProject "Popsicle" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D5FBF54C1BE65BB600F3CB79 /* Debug */,
D5FBF54D1BE65BB600F3CB79 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D5FBF54E1BE65BB600F3CB79 /* Build configuration list for PBXNativeTarget "Popsicle" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D5FBF54F1BE65BB600F3CB79 /* Debug */,
D5FBF5501BE65BB600F3CB79 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D5FBF5311BE65BB500F3CB79 /* Project object */;
}
================================================
FILE: Popsicle.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:Popsicle.xcodeproj">
</FileRef>
</Workspace>
================================================
FILE: Popsicle.xcodeproj/xcshareddata/xcschemes/Popsicle.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5FBF5391BE65BB500F3CB79"
BuildableName = "Popsicle.framework"
BlueprintName = "Popsicle"
ReferencedContainer = "container:Popsicle.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5FBF5431BE65BB500F3CB79"
BuildableName = "PopsicleTests.xctest"
BlueprintName = "PopsicleTests"
ReferencedContainer = "container:Popsicle.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5FBF5391BE65BB500F3CB79"
BuildableName = "Popsicle.framework"
BlueprintName = "Popsicle"
ReferencedContainer = "container:Popsicle.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5FBF5391BE65BB500F3CB79"
BuildableName = "Popsicle.framework"
BlueprintName = "Popsicle"
ReferencedContainer = "container:Popsicle.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D5FBF5391BE65BB500F3CB79"
BuildableName = "Popsicle.framework"
BlueprintName = "Popsicle"
ReferencedContainer = "container:Popsicle.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
================================================
FILE: PopsicleDemo/AppDelegate.swift
================================================
//
// AppDelegate.swift
// PopsicleDemo
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window?.rootViewController = UINavigationController(rootViewController: ViewController())
self.window?.makeKeyAndVisible()
return true
}
}
================================================
FILE: PopsicleDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-40@2x-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-29.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-29@2x-1.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-40.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-83.5@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: PopsicleDemo/Assets.xcassets/Contents.json
================================================
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: PopsicleDemo/Assets.xcassets/logo.imageset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"filename" : "logo.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
================================================
FILE: PopsicleDemo/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
================================================
FILE: PopsicleDemo/DRPageScrollView.h
================================================
//
// DRPageScrollView.h
// DRPageScrollView
//
// Created by David Román Aguirre on 3/4/15.
// Copyright (c) 2015 David Román Aguirre. All rights reserved.
//
#import <UIKit/UIKit.h>
/// The type of block used to define what to display on each page view.
typedef void(^DRPageHandlerBlock)(UIView *pageView);
@interface DRPageScrollView : UIScrollView
/// Determines whether page views are reused or not in order to reduce memory consumption.
@property (nonatomic, getter=isPageReuseEnabled) BOOL pageReuseEnabled;
/// The current page index (starting from 0).
@property (nonatomic, assign) NSInteger currentPage;
/// The total number of pages in the scroll view.
@property (nonatomic, readonly) NSInteger numberOfPages;
/**
* Sets up a new page for the scroll view.
*
* @param handler A block that defines what to display on the page.
**/
- (void)addPageWithHandler:(DRPageHandlerBlock)handler;
@end
================================================
FILE: PopsicleDemo/DRPageScrollView.m
================================================
//
// DRPageScrollView.m
// DRPageScrollView
//
// Created by David Román Aguirre on 3/4/15.
// Copyright (c) 2015 David Román Aguirre. All rights reserved.
//
#import "DRPageScrollView.h"
@interface DRPageScrollView () {
NSInteger previousPage;
NSInteger instantaneousPreviousPage;
}
@property (nonatomic, strong) NSArray *pageViews;
@property (nonatomic, strong) NSArray *pageHandlers;
@end
@implementation DRPageScrollView
- (instancetype)init {
if (self = [super init]) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self commonInit];
}
return self;
}
- (void)commonInit {
previousPage = -1;
self.pagingEnabled = YES;
self.showsHorizontalScrollIndicator = NO;
self.showsVerticalScrollIndicator = NO;
self.pageViews = [NSMutableArray new];
self.pageHandlers = [NSArray new];
}
- (void)setPageReuseEnabled:(BOOL)pageReuseEnabled {
if (self.numberOfPages > 0) return;
_pageReuseEnabled = pageReuseEnabled;
}
- (NSInteger)currentPage {
CGPoint presentationLayerContentOffset = [self.layer.presentationLayer bounds].origin;
return MAX(round(presentationLayerContentOffset.x/self.frame.size.width), 0);
}
- (void)setCurrentPage:(NSInteger)currentPage {
self.contentOffset = CGPointMake(self.frame.size.width*currentPage, self.contentOffset.y);
}
- (NSInteger)numberOfPages {
return [self.pageHandlers count];
}
- (void)addPageWithHandler:(DRPageHandlerBlock)handler {
self.pageHandlers = [self.pageHandlers arrayByAddingObject:handler];
}
#pragma mark Pages
- (BOOL)isAnimating {
return [[self.layer animationKeys] count] != 0;
}
- (void)setContentOffset:(CGPoint)contentOffset {
[super setContentOffset:contentOffset];
if ([self isAnimating]) {
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(didRefreshDisplay:)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
} else {
[self didScrollToPosition:contentOffset];
}
}
- (void)didRefreshDisplay:(CADisplayLink *)displayLink {
if ([self isAnimating]) {
CGPoint presentationLayerContentOffset = [self.layer.presentationLayer bounds].origin;
[self didScrollToPosition:presentationLayerContentOffset];
} else {
[displayLink invalidate];
}
}
- (void)didScrollToPosition:(CGPoint)position {
if (self.numberOfPages == 0 || self.currentPage == previousPage) return;
if (self.pageReuseEnabled) {
for (UIView *pageView in self.pageViews) {
if (pageView.tag < self.currentPage - 1 || pageView.tag > self.currentPage + 1) {
[self queuePageView:pageView];
}
}
}
for (NSInteger i = self.currentPage-1; i <= self.currentPage+1; i++) {
if (i >= 0 && i < self.numberOfPages && ![self pageViewWithTag:i]) {
UIView *pageView = [self dequeuePageView];
pageView.tag = i;
DRPageHandlerBlock handler = self.pageHandlers[i];
handler(pageView);
[self addSubview:pageView];
NSInteger pageMultiplier = 2*i+1; // We need an odd multiplier. Any odd number can be expressed as 2n+1.
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:pageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:pageMultiplier constant:0];
NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:pageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:pageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1 constant:0];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:pageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
[self addConstraints:@[centerXConstraint, centerYConstraint, widthConstraint, heightConstraint]]; // This may lead to vertical orientation support in the future ;)
}
}
previousPage = self.currentPage;
}
- (void)queuePageView:(UIView *)pageView {
[pageView removeFromSuperview];
for (UIView *sb in pageView.subviews) {
[sb removeFromSuperview];
}
pageView.tag = -1;
}
- (UIView *)dequeuePageView {
for (UIView *pv in self.pageViews) {
if (!pv.superview) {
return pv;
}
}
UIView *pageView = [UIView new];
pageView.tag = -1;
pageView.translatesAutoresizingMaskIntoConstraints = NO;
self.pageViews = [self.pageViews arrayByAddingObject:pageView];
return pageView;
}
- (UIView *)pageViewWithTag:(NSInteger)tag {
for (UIView *pageView in self.subviews) {
if (pageView.tag == tag && pageView.class == [UIView class]) {
return pageView;
}
}
return nil;
}
#pragma mark Rotation/resize
- (void)layoutSubviews {
CGFloat neededContentSizeWidth = self.frame.size.width*self.numberOfPages;
if (self.contentSize.width != neededContentSizeWidth) {
[self refreshDimensions];
self.currentPage = instantaneousPreviousPage;
} else {
instantaneousPreviousPage = self.currentPage;
}
[super layoutSubviews];
}
- (void)refreshDimensions {
self.contentSize = CGSizeMake(self.frame.size.width*self.numberOfPages, self.frame.size.height);
self.contentInset = UIEdgeInsetsZero;
}
@end
================================================
FILE: PopsicleDemo/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Popsicle</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
================================================
FILE: PopsicleDemo/PageScrollView.swift
================================================
//
// PageScrollView.swift
// Popsicle
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
import UIKit
class FirstPageView: UIView {
@IBOutlet weak var label: UILabel?
@IBOutlet weak var imageView: UIImageView?
}
class SecondPageView: UIView {
@IBOutlet weak var label: UILabel?
}
class ThirdPageView: UIView {
@IBOutlet weak var label1: UILabel?
@IBOutlet weak var label2: UILabel?
}
class FourthPageView: UIView {
@IBOutlet weak var label: UILabel?
}
class PageScrollView: DRPageScrollView {
let firstPageView: FirstPageView
let secondPageView: SecondPageView
let thirdPageView: ThirdPageView
let fourthPageView: FourthPageView
override init(frame: CGRect) {
let views = UIView.viewsByClassInNibNamed("PageViews")
self.firstPageView = views["PopsicleDemo.FirstPageView"] as! FirstPageView
self.secondPageView = views["PopsicleDemo.SecondPageView"] as! SecondPageView
self.thirdPageView = views["PopsicleDemo.ThirdPageView"] as! ThirdPageView
self.fourthPageView = views["PopsicleDemo.FourthPageView"] as! FourthPageView
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func didMoveToSuperview() {
if self.superview != nil {
for pv in [firstPageView, secondPageView, thirdPageView, fourthPageView] {
self.addPageWithHandler { pageView in
pageView.addSubview(pv)
pv.pinToSuperviewEdges()
}
}
}
}
}
================================================
FILE: PopsicleDemo/PageViews.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="FirstPageView" customModule="PopsicleDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Welcome to this demo of Popsicle" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ecS-oi-gEe">
<rect key="frame" x="171" y="549.5" width="259.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="logo" translatesAutoresizingMaskIntoConstraints="NO" id="6y5-6A-Jqb">
<rect key="frame" x="172" y="172" width="256" height="256"/>
<constraints>
<constraint firstAttribute="width" constant="256" id="HP8-Kb-mIE"/>
<constraint firstAttribute="height" constant="256" id="xDP-1k-OEj"/>
</constraints>
</imageView>
</subviews>
<constraints>
<constraint firstItem="ecS-oi-gEe" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="iN0-l3-epB" secondAttribute="leading" constant="30" id="4JZ-tg-q2N"/>
<constraint firstAttribute="centerX" secondItem="ecS-oi-gEe" secondAttribute="centerX" id="LIr-Vw-5cn"/>
<constraint firstAttribute="centerY" secondItem="6y5-6A-Jqb" secondAttribute="centerY" id="ku4-Hi-Zyi"/>
<constraint firstAttribute="centerX" secondItem="6y5-6A-Jqb" secondAttribute="centerX" id="sF6-vM-KOf"/>
<constraint firstAttribute="bottom" secondItem="ecS-oi-gEe" secondAttribute="bottom" constant="30" id="xkO-DG-nPj"/>
</constraints>
<connections>
<outlet property="imageView" destination="6y5-6A-Jqb" id="tzf-O6-3ix"/>
<outlet property="label" destination="ecS-oi-gEe" id="pTx-fd-ibf"/>
</connections>
<point key="canvasLocation" x="393" y="403"/>
</view>
<view contentMode="scaleToFill" id="I3K-66-IeR" customClass="SecondPageView" customModule="PopsicleDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iib-Tg-Cyj">
<rect key="frame" x="44" y="179.5" width="512" height="81.5"/>
<string key="text">That was smooth!
As you can see, Popsicle provides a great way to create transitions through value interpolations.</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="centerX" secondItem="iib-Tg-Cyj" secondAttribute="centerX" id="HG8-QR-See"/>
<constraint firstItem="iib-Tg-Cyj" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="I3K-66-IeR" secondAttribute="leading" constant="30" id="JPf-6l-Scg"/>
<constraint firstAttribute="centerY" secondItem="iib-Tg-Cyj" secondAttribute="centerY" constant="80" id="Udi-CK-c1O"/>
</constraints>
<connections>
<outlet property="label" destination="iib-Tg-Cyj" id="7Vt-NB-TYi"/>
</connections>
<point key="canvasLocation" x="1135" y="403"/>
</view>
<view contentMode="scaleToFill" id="lSl-j6-h40" customClass="ThirdPageView" customModule="PopsicleDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ijd-gD-Pdk">
<rect key="frame" x="36" y="239" width="528.5" height="61"/>
<string key="text">Interpolations are not bound to UIKit values, although Popsicle offers built-in support for widely used types such CGFloat, CGAffineTransform and UIColor.</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="textColor">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yOi-JI-a0I">
<rect key="frame" x="30" y="350" width="540.5" height="41"/>
<string key="text">In addition to that, Popsicle takes advantage of Swift's best features such as generics and subscripts, making it really sweet to use.</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="textColor">
<color key="value" white="1" alpha="1" colorSpace="calibratedWhite"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</label>
</subviews>
<constraints>
<constraint firstItem="yOi-JI-a0I" firstAttribute="top" secondItem="lSl-j6-h40" secondAttribute="centerY" constant="50" id="5xz-In-fDV"/>
<constraint firstItem="yOi-JI-a0I" firstAttribute="centerX" secondItem="lSl-j6-h40" secondAttribute="centerX" id="6Nq-hu-RdY"/>
<constraint firstItem="yOi-JI-a0I" firstAttribute="leading" secondItem="lSl-j6-h40" secondAttribute="leading" constant="30" id="R0Q-Q4-0CB"/>
<constraint firstAttribute="centerY" secondItem="ijd-gD-Pdk" secondAttribute="bottom" id="nOG-cc-EOM"/>
<constraint firstAttribute="centerX" secondItem="ijd-gD-Pdk" secondAttribute="centerX" id="vJw-lL-OL9"/>
<constraint firstItem="ijd-gD-Pdk" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="lSl-j6-h40" secondAttribute="leading" constant="30" id="yZM-gD-9ft"/>
</constraints>
<connections>
<outlet property="label1" destination="ijd-gD-Pdk" id="3Ld-kl-1zB"/>
<outlet property="label2" destination="yOi-JI-a0I" id="dOF-QM-xoB"/>
</connections>
<point key="canvasLocation" x="1890" y="403"/>
</view>
<view contentMode="scaleToFill" id="pIp-qb-tLI" customClass="FourthPageView" customModule="PopsicleDemo" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="For requests, comments or concerns, just open a GitHub issue or ping me @DavdRoman." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4nl-Ho-8yk">
<rect key="frame" x="31" y="280" width="538.5" height="41"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="centerX" secondItem="4nl-Ho-8yk" secondAttribute="centerX" id="I9N-AY-ig8"/>
<constraint firstAttribute="centerY" secondItem="4nl-Ho-8yk" secondAttribute="centerY" id="T0O-jF-phJ"/>
<constraint firstItem="4nl-Ho-8yk" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="pIp-qb-tLI" secondAttribute="leading" constant="30" id="idu-Sz-fiy"/>
</constraints>
<connections>
<outlet property="label" destination="4nl-Ho-8yk" id="h0M-xJ-h3S"/>
</connections>
<point key="canvasLocation" x="2614" y="403"/>
</view>
</objects>
<resources>
<image name="logo" width="512" height="512"/>
</resources>
</document>
================================================
FILE: PopsicleDemo/PopsicleDemo-Bridging-Header.h
================================================
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "DRPageScrollView.h"
================================================
FILE: PopsicleDemo/UIView+Utils.swift
================================================
//
// UIView+Utils.swift
// Popsicle
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
extension UIView {
static func viewsByClassInNibNamed(name: String) -> [String: UIView] {
var viewsByClass = [String: UIView]()
let nibViews = NSBundle.mainBundle().loadNibNamed(name, owner: self, options: nil)
for view in nibViews {
if let v = view as? UIView {
viewsByClass[NSStringFromClass(v.dynamicType)] = v
}
}
return viewsByClass
}
func pinToSuperviewEdges() {
self.translatesAutoresizingMaskIntoConstraints = false
for attribute in [.Top, .Left, .Bottom, .Right] as [NSLayoutAttribute] {
let constraint = NSLayoutConstraint(item: self, attribute: attribute, relatedBy: .Equal, toItem: self.superview, attribute: attribute, multiplier: 1, constant: 0)
self.superview?.addConstraint(constraint)
}
}
}
================================================
FILE: PopsicleDemo/ViewController.swift
================================================
//
// ViewController.swift
// PopsicleDemo
//
// Created by David Román Aguirre on 04/11/15.
// Copyright © 2015 David Román Aguirre. All rights reserved.
//
import UIKit
import Popsicle
class ViewController: UIViewController, UIScrollViewDelegate {
let pageScrollView: PageScrollView
let interpolator: Interpolator
init() {
self.pageScrollView = PageScrollView(frame: CGRectZero)
self.interpolator = Interpolator()
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Popsicle"
self.view.backgroundColor = UIColor.whiteColor()
self.pageScrollView.delegate = self
self.view.addSubview(self.pageScrollView)
self.pageScrollView.pinToSuperviewEdges()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.interpolator.removeAllInterpolations()
let backgroundColorInterpolation = Interpolation(self.view, backgroundColor)
backgroundColorInterpolation[1, 3] = UIColor.whiteColor()
backgroundColorInterpolation[1.7, 2] = UIColor(red: 254/255, green: 134/255, blue: 44/255, alpha: 1)
self.interpolator.addInterpolation(backgroundColorInterpolation)
let barTintColorInterpolation = Interpolation(self.navigationController!.navigationBar, barTintColor)
barTintColorInterpolation[1, 3] = UIColor.whiteColor()
barTintColorInterpolation[1.7, 2] = UIColor(red: 244255, green: 219/255, blue: 165/255, alpha: 1)
self.interpolator.addInterpolation(barTintColorInterpolation)
if let imageView = self.pageScrollView.firstPageView.imageView {
let xInterpolation = Interpolation(imageView, centerXConstraint)
xInterpolation[0] = 0
xInterpolation.setEasingFunction(EasingFunctionEaseInQuad, forTime: 0)
xInterpolation[1] = -self.pageScrollView.frame.width
xInterpolation[2] = -self.pageScrollView.frame.width*2
xInterpolation[3] = -self.pageScrollView.frame.width*3
self.interpolator.addInterpolation(xInterpolation)
let yInterpolation = Interpolation(imageView, centerYConstraint)
yInterpolation[0] = 0
yInterpolation[1, 2] = -self.pageScrollView.frame.height/2+80
yInterpolation[3] = 0
self.interpolator.addInterpolation(yInterpolation)
let alphaInterpolation = Interpolation(imageView, alpha)
alphaInterpolation[1] = 1
alphaInterpolation[2] = 0
alphaInterpolation[3] = 0.25
self.interpolator.addInterpolation(alphaInterpolation)
let transformInterpolation = Interpolation(imageView, transform)
transformInterpolation[0, 1, 2] = CGAffineTransformIdentity
transformInterpolation[0.25] = CGAffineTransformMake(0, 0, 1.1, 1.1, 0)
transformInterpolation[3] = CGAffineTransformMake(0, 0, 1.4, 1.4, 60)
self.interpolator.addInterpolation(transformInterpolation)
}
if let label1 = self.pageScrollView.firstPageView.label {
let alphaInterpolation = Interpolation(label1, alpha)
alphaInterpolation[0] = 1
alphaInterpolation[0.4] = 0
self.interpolator.addInterpolation(alphaInterpolation)
}
if let label2 = self.pageScrollView.secondPageView.label {
let scaleInterpolation = Interpolation(label2, transform)
scaleInterpolation[0] = CGAffineTransformMake(0, 0, 0.6, 0.6, 0)
scaleInterpolation[1] = CGAffineTransformMake(0, 0, 1, 1, 0)
self.interpolator.addInterpolation(scaleInterpolation)
let alphaInterpolation = Interpolation(label2, alpha)
alphaInterpolation[1] = 1
alphaInterpolation[1.7] = 0
self.interpolator.addInterpolation(alphaInterpolation)
}
if let label3 = self.pageScrollView.thirdPageView.label1, let label4 = self.pageScrollView.thirdPageView.label2 {
let translateInterpolation1 = Interpolation(label3, transform)
translateInterpolation1[1] = CGAffineTransformMake(100, 0, 1, 1, 0)
translateInterpolation1[2] = CGAffineTransformIdentity
translateInterpolation1[3] = CGAffineTransformMake(-100, 0, 1, 1, 0)
self.interpolator.addInterpolation(translateInterpolation1)
let translateInterpolation2 = Interpolation(label4, transform)
translateInterpolation2[1] = CGAffineTransformMake(300, 0, 1, 1, 0)
translateInterpolation2[2] = CGAffineTransformIdentity
translateInterpolation2[3] = CGAffineTransformMake(-300, 0, 1, 1, 0)
self.interpolator.addInterpolation(translateInterpolation2)
}
}
func scrollViewDidScroll(scrollView: UIScrollView) {
self.interpolator.time = Double(scrollView.contentOffset.x/scrollView.frame.size.width)
}
}
================================================
FILE: README.md
================================================
> **THIS PROJECT IS NO LONGER MAINTAINED.**
---
<p align="center">
<img src="Assets/header.png" alt="Popsicle header" width="520px" />
</p>
<p align="center">
<a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg" alt="Carthage compatible" /></a>
<a href="https://cocoapods.org/pods/Popsicle"><img src="https://img.shields.io/cocoapods/v/Popsicle.svg" alt="CocoaPods compatible" /></a>
</p>
<p align="center">
<img src="Assets/1.gif" alt="GIF 1" width="320px" />
</p>
Popsicle is a Swift framework for creating and managing interpolations of different value types with built-in UIKit support.
## Installation
#### Carthage
```
github "DavdRoman/Popsicle"
```
#### CocoaPods
```ruby
pod 'Popsicle'
```
#### Manual
Drag and copy all files in the [__Popsicle__](Popsicle) folder into your project.
## At a glance
#### Interpolating UIView (or any other NSObject) values
First, you need an `Interpolator` instance:
```swift
let interpolator = Interpolator()
```
Next, you need to add some `Interpolation<T>` instances to your interpolator. In the example below, we are going to interpolate the alpha value of a UIView for times between 0 and 150:
```swift
let interpolation = Interpolation(yourView, alpha)
interpolation[0] = 0
interpolation[150] = 1
self.interpolator.addInterpolation(interpolation)
```
Note `alpha` is a built-in `KeyPath<T, U>` constant. Popsicle offers a nice set of [__UIKit-related KeyPaths__](Popsicle/KeyPath.swift) ready to be used. You may also use a completely custom key path.
You can also modify the easing function used at a given time:
```swift
interpolation.setEasingFunction(EasingFunctionEaseOutQuad, forTime: 0)
```
There's a bunch of [__built-in easing functions__](Popsicle/EasingFunction.swift) to choose from.
Finally, just make your `interpolator` vary its `time` depending on whatever you want. For example, the content offset of a `UITableView`:
```swift
func scrollViewDidScroll(scrollView: UIScrollView) {
interpolator.time = Double(scrollView.contentOffset.y)
}
```
#### Interpolating custom values
You can declare a value type as interpolable by making it conform to the `Interpolable` protocol.
As an example, check out how `CGPoint` conforms to `Interpolable`:
```swift
extension CGSize: Interpolable {
public static func interpolate(from fromValue: CGSize, to toValue: CGSize, withProgress progress: Progress) -> CGSize {
let width = CGFloat.interpolate(from: fromValue.width, to: toValue.width, withProgress: progress)
let height = CGFloat.interpolate(from: fromValue.height, to: toValue.height, withProgress: progress)
return CGSizeMake(width, height)
}
public static func objectify(value: CGSize) -> AnyObject {
return NSValue(CGSize: value)
}
}
```
## License
Popsicle is available under the MIT license.
gitextract_ps5q6ues/ ├── .gitignore ├── LICENSE ├── Popsicle/ │ ├── EasingFunction.swift │ ├── Info.plist │ ├── Interpolable.swift │ ├── Interpolation.swift │ ├── Interpolator.swift │ ├── KeyPath.swift │ └── Popsicle.h ├── Popsicle.podspec ├── Popsicle.xcodeproj/ │ ├── project.pbxproj │ ├── project.xcworkspace/ │ │ └── contents.xcworkspacedata │ └── xcshareddata/ │ └── xcschemes/ │ └── Popsicle.xcscheme ├── PopsicleDemo/ │ ├── AppDelegate.swift │ ├── Assets.xcassets/ │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── logo.imageset/ │ │ └── Contents.json │ ├── Base.lproj/ │ │ └── LaunchScreen.storyboard │ ├── DRPageScrollView.h │ ├── DRPageScrollView.m │ ├── Info.plist │ ├── PageScrollView.swift │ ├── PageViews.xib │ ├── PopsicleDemo-Bridging-Header.h │ ├── UIView+Utils.swift │ └── ViewController.swift └── README.md
Condensed preview — 27 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (90K chars).
[
{
"path": ".gitignore",
"chars": 232,
"preview": "# OS X\n\n.DS_Store\n\n# Xcode\n\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.pe"
},
{
"path": "LICENSE",
"chars": 1107,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2015 IFTTT Inc\nCopyright (c) 2015 David Román\n\nPermission is hereby granted, free o"
},
{
"path": "Popsicle/EasingFunction.swift",
"chars": 1630,
"preview": "//\n// EasingFunction.swift\n// RazzleDazzle\n//\n// Created by Laura Skelton on 6/15/15.\n// Copyright (c) 2015 IFTTT. A"
},
{
"path": "Popsicle/Info.plist",
"chars": 808,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "Popsicle/Interpolable.swift",
"chars": 6492,
"preview": "//\n// Interpolable.swift\n// Popsicle\n//\n// Created by David Román Aguirre on 01/11/15.\n// Copyright © 2015 David Rom"
},
{
"path": "Popsicle/Interpolation.swift",
"chars": 3874,
"preview": "//\n// Interpolation.swift\n// Popsicle\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 David Ro"
},
{
"path": "Popsicle/Interpolator.swift",
"chars": 1492,
"preview": "//\n// Interpolator.swift\n// Popsicle\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 David Rom"
},
{
"path": "Popsicle/KeyPath.swift",
"chars": 6037,
"preview": "//\n// KeyPath.swift\n// Popsicle\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 David Román Ag"
},
{
"path": "Popsicle/Popsicle.h",
"chars": 494,
"preview": "//\n// Popsicle.h\n// Popsicle\n//\n// Created by David Román Aguirre on 01/11/15.\n// Copyright © 2015 David Román Aguir"
},
{
"path": "Popsicle.podspec",
"chars": 753,
"preview": "Pod::Spec.new do |s|\n s.name = \"Popsicle\"\n s.version = \"2.0.1\"\n s.summary "
},
{
"path": "Popsicle.xcodeproj/project.pbxproj",
"chars": 21715,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "Popsicle.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 153,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:Popsicle.xcodep"
},
{
"path": "Popsicle.xcodeproj/xcshareddata/xcschemes/Popsicle.xcscheme",
"chars": 3658,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n LastUpgradeVersion = \"0710\"\n version = \"1.3\">\n <BuildAction\n "
},
{
"path": "PopsicleDemo/AppDelegate.swift",
"chars": 616,
"preview": "//\n// AppDelegate.swift\n// PopsicleDemo\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 David "
},
{
"path": "PopsicleDemo/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 1641,
"preview": "{\n \"images\" : [\n {\n \"size\" : \"29x29\",\n \"idiom\" : \"iphone\",\n \"filename\" : \"Icon-29@2x.png\",\n \"sca"
},
{
"path": "PopsicleDemo/Assets.xcassets/Contents.json",
"chars": 62,
"preview": "{\n \"info\" : {\n \"version\" : 1,\n \"author\" : \"xcode\"\n }\n}"
},
{
"path": "PopsicleDemo/Assets.xcassets/logo.imageset/Contents.json",
"chars": 153,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"filename\" : \"logo.pdf\"\n }\n ],\n \"info\" : {\n \"version\" "
},
{
"path": "PopsicleDemo/Base.lproj/LaunchScreen.storyboard",
"chars": 1663,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
},
{
"path": "PopsicleDemo/DRPageScrollView.h",
"chars": 916,
"preview": "//\n// DRPageScrollView.h\n// DRPageScrollView\n//\n// Created by David Román Aguirre on 3/4/15.\n// Copyright (c) 2015 D"
},
{
"path": "PopsicleDemo/DRPageScrollView.m",
"chars": 5445,
"preview": "//\n// DRPageScrollView.m\n// DRPageScrollView\n//\n// Created by David Román Aguirre on 3/4/15.\n// Copyright (c) 2015 D"
},
{
"path": "PopsicleDemo/Info.plist",
"chars": 1434,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
},
{
"path": "PopsicleDemo/PageScrollView.swift",
"chars": 1516,
"preview": "//\n// PageScrollView.swift\n// Popsicle\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 David R"
},
{
"path": "PopsicleDemo/PageViews.xib",
"chars": 11282,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" versi"
},
{
"path": "PopsicleDemo/PopsicleDemo-Bridging-Header.h",
"chars": 132,
"preview": "//\n// Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n#import \"DRPageS"
},
{
"path": "PopsicleDemo/UIView+Utils.swift",
"chars": 906,
"preview": "//\n// UIView+Utils.swift\n// Popsicle\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 David Rom"
},
{
"path": "PopsicleDemo/ViewController.swift",
"chars": 4518,
"preview": "//\n// ViewController.swift\n// PopsicleDemo\n//\n// Created by David Román Aguirre on 04/11/15.\n// Copyright © 2015 Dav"
},
{
"path": "README.md",
"chars": 2867,
"preview": "> **THIS PROJECT IS NO LONGER MAINTAINED.**\n\n---\n\n<p align=\"center\">\n\t<img src=\"Assets/header.png\" alt=\"Popsicle header\""
}
]
About this extraction
This page contains the full source code of the DavdRoman/Popsicle GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 27 files (79.7 KB), approximately 23.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.