diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/CollectionViewWaterfallLayout.podspec b/CollectionViewWaterfallLayout.podspec index 3016e6a..0dc2bd6 100644 --- a/CollectionViewWaterfallLayout.podspec +++ b/CollectionViewWaterfallLayout.podspec @@ -13,6 +13,6 @@ Pod::Spec.new do |s| s.social_media_url = 'https://twitter.com/ecerney' s.ios.deployment_target = '8.0' s.swift_versions = '5.0' - s.source_files = 'CollectionViewWaterfallLayout.swift' + s.source_files = 'Sources/CollectionViewWaterfallLayout/CollectionViewWaterfallLayout.swift' s.frameworks = 'UIKit' end diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..146bb96 --- /dev/null +++ b/Package.swift @@ -0,0 +1,28 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "CollectionViewWaterfallLayout", + platforms: [ + .iOS(.v8) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "CollectionViewWaterfallLayout", + targets: ["CollectionViewWaterfallLayout"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "CollectionViewWaterfallLayout", + dependencies: []) + ] +) diff --git a/README.md b/README.md index 592e405..0357c29 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,19 @@ Prerequisites Installation ----------- +## Cocoapods CollectionViewWaterfallLayout is available through CocoaPods. To install it, simply add the following line to your Podfile: ``` pod "CollectionViewWaterfallLayout" ``` +## Swift Package Manager + +CollectionViewWaterfallLayout can be installed via Swift Package Manager. To use it in your project, open Xcode, go to menu File -> Swift Packages -> Add Package Dependency, and paste this repo's URL: +``` +https://github.com/ecerney/CollectionViewWaterfallLayout.git +``` + How to Use ----------- diff --git a/CollectionViewWaterfallLayout.swift b/Sources/CollectionViewWaterfallLayout/CollectionViewWaterfallLayout.swift similarity index 98% rename from CollectionViewWaterfallLayout.swift rename to Sources/CollectionViewWaterfallLayout/CollectionViewWaterfallLayout.swift index 06dbf64..3c81cf6 100644 --- a/CollectionViewWaterfallLayout.swift +++ b/Sources/CollectionViewWaterfallLayout/CollectionViewWaterfallLayout.swift @@ -90,11 +90,8 @@ public class CollectionViewWaterfallLayout: UICollectionViewLayout { } // MARK: - Private Properties - private weak var delegate: CollectionViewWaterfallLayoutDelegate? { - get { - return collectionView?.delegate as? CollectionViewWaterfallLayoutDelegate - } - } + weak var delegate: CollectionViewWaterfallLayoutDelegate? + private var columnHeights = [Float]() private var sectionItemAttributes = [[UICollectionViewLayoutAttributes]]() private var allItemAttributes = [UICollectionViewLayoutAttributes]() @@ -102,6 +99,12 @@ public class CollectionViewWaterfallLayout: UICollectionViewLayout { private var footersAttribute = [Int: UICollectionViewLayoutAttributes]() private var unionRects = [CGRect]() + // MARK: - Initialization + public convenience init(delegate: CollectionViewWaterfallLayoutDelegate) { + self.init() + self.delegate = delegate + } + // MARK: - UICollectionViewLayout Methods public override func prepare() { super.prepare() diff --git a/WaterfallDemo/CollectionViewWaterfallLayoutDemo.xcodeproj/project.pbxproj b/WaterfallDemo/CollectionViewWaterfallLayoutDemo.xcodeproj/project.pbxproj index bedb6c8..e20dd9f 100644 --- a/WaterfallDemo/CollectionViewWaterfallLayoutDemo.xcodeproj/project.pbxproj +++ b/WaterfallDemo/CollectionViewWaterfallLayoutDemo.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -13,20 +13,9 @@ 029C0A2D197E226600DA6FE9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029C0A2C197E226600DA6FE9 /* ViewController.swift */; }; 029C0A30197E226600DA6FE9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 029C0A2E197E226600DA6FE9 /* Main.storyboard */; }; 029C0A32197E226600DA6FE9 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 029C0A31197E226600DA6FE9 /* Images.xcassets */; }; - 029C0A3E197E226600DA6FE9 /* WaterfallFlowLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029C0A3D197E226600DA6FE9 /* WaterfallFlowLayoutTests.swift */; }; - 029C0A4C19802E5E00DA6FE9 /* CollectionViewWaterfallLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 029C0A4B19802E5E00DA6FE9 /* CollectionViewWaterfallLayout.swift */; }; + 30F6564B2591EF8C005EFF4B /* CollectionViewWaterfallLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 30F6564A2591EF8C005EFF4B /* CollectionViewWaterfallLayout */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 029C0A38197E226600DA6FE9 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 029C0A1D197E226600DA6FE9 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 029C0A24197E226600DA6FE9; - remoteInfo = WaterfallFlowLayout; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXFileReference section */ 026447C0233ADD4300271918 /* LabelCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCollectionViewCell.swift; sourceTree = ""; }; 026447C2233AE30900271918 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; @@ -36,10 +25,7 @@ 029C0A2C197E226600DA6FE9 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 029C0A2F197E226600DA6FE9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 029C0A31197E226600DA6FE9 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 029C0A37197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CollectionViewWaterfallLayoutDemo.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 029C0A3C197E226600DA6FE9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 029C0A3D197E226600DA6FE9 /* WaterfallFlowLayoutTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaterfallFlowLayoutTests.swift; sourceTree = ""; }; - 029C0A4B19802E5E00DA6FE9 /* CollectionViewWaterfallLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CollectionViewWaterfallLayout.swift; path = ../../CollectionViewWaterfallLayout.swift; sourceTree = ""; }; + 30F656472591EF83005EFF4B /* CollectionViewWaterfallLayout */ = {isa = PBXFileReference; lastKnownFileType = folder; name = CollectionViewWaterfallLayout; path = ..; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -47,13 +33,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 029C0A34197E226600DA6FE9 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( + 30F6564B2591EF8C005EFF4B /* CollectionViewWaterfallLayout in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -63,9 +43,10 @@ 029C0A1C197E226600DA6FE9 = { isa = PBXGroup; children = ( + 30F656472591EF83005EFF4B /* CollectionViewWaterfallLayout */, 029C0A27197E226600DA6FE9 /* WaterfallFlowLayout */, - 029C0A3A197E226600DA6FE9 /* WaterfallFlowLayoutTests */, 029C0A26197E226600DA6FE9 /* Products */, + 30F656492591EF8C005EFF4B /* Frameworks */, ); sourceTree = ""; }; @@ -73,7 +54,6 @@ isa = PBXGroup; children = ( 029C0A25197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo.app */, - 029C0A37197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo.xctest */, ); name = Products; sourceTree = ""; @@ -86,7 +66,6 @@ 026447C0233ADD4300271918 /* LabelCollectionViewCell.swift */, 029C0A2E197E226600DA6FE9 /* Main.storyboard */, 026447C2233AE30900271918 /* LaunchScreen.storyboard */, - 029C0A4B19802E5E00DA6FE9 /* CollectionViewWaterfallLayout.swift */, 029C0A31197E226600DA6FE9 /* Images.xcassets */, 029C0A28197E226600DA6FE9 /* Supporting Files */, ); @@ -101,21 +80,11 @@ name = "Supporting Files"; sourceTree = ""; }; - 029C0A3A197E226600DA6FE9 /* WaterfallFlowLayoutTests */ = { - isa = PBXGroup; - children = ( - 029C0A3D197E226600DA6FE9 /* WaterfallFlowLayoutTests.swift */, - 029C0A3B197E226600DA6FE9 /* Supporting Files */, - ); - path = WaterfallFlowLayoutTests; - sourceTree = ""; - }; - 029C0A3B197E226600DA6FE9 /* Supporting Files */ = { + 30F656492591EF8C005EFF4B /* Frameworks */ = { isa = PBXGroup; children = ( - 029C0A3C197E226600DA6FE9 /* Info.plist */, ); - name = "Supporting Files"; + name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ @@ -134,28 +103,13 @@ dependencies = ( ); name = CollectionViewWaterfallLayoutDemo; + packageProductDependencies = ( + 30F6564A2591EF8C005EFF4B /* CollectionViewWaterfallLayout */, + ); productName = WaterfallFlowLayout; productReference = 029C0A25197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo.app */; productType = "com.apple.product-type.application"; }; - 029C0A36197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemoTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 029C0A44197E226600DA6FE9 /* Build configuration list for PBXNativeTarget "CollectionViewWaterfallLayoutDemoTests" */; - buildPhases = ( - 029C0A33197E226600DA6FE9 /* Sources */, - 029C0A34197E226600DA6FE9 /* Frameworks */, - 029C0A35197E226600DA6FE9 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 029C0A39197E226600DA6FE9 /* PBXTargetDependency */, - ); - name = CollectionViewWaterfallLayoutDemoTests; - productName = WaterfallFlowLayoutTests; - productReference = 029C0A37197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -169,10 +123,6 @@ 029C0A24197E226600DA6FE9 = { CreatedOnToolsVersion = 6.0; }; - 029C0A36197E226600DA6FE9 = { - CreatedOnToolsVersion = 6.0; - TestTargetID = 029C0A24197E226600DA6FE9; - }; }; }; buildConfigurationList = 029C0A20197E226600DA6FE9 /* Build configuration list for PBXProject "CollectionViewWaterfallLayoutDemo" */; @@ -189,7 +139,6 @@ projectRoot = ""; targets = ( 029C0A24197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo */, - 029C0A36197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemoTests */, ); }; /* End PBXProject section */ @@ -205,13 +154,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 029C0A35197E226600DA6FE9 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -221,29 +163,12 @@ files = ( 029C0A2D197E226600DA6FE9 /* ViewController.swift in Sources */, 029C0A2B197E226600DA6FE9 /* AppDelegate.swift in Sources */, - 029C0A4C19802E5E00DA6FE9 /* CollectionViewWaterfallLayout.swift in Sources */, 026447C1233ADD4300271918 /* LabelCollectionViewCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 029C0A33197E226600DA6FE9 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 029C0A3E197E226600DA6FE9 /* WaterfallFlowLayoutTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 029C0A39197E226600DA6FE9 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 029C0A24197E226600DA6FE9 /* CollectionViewWaterfallLayoutDemo */; - targetProxy = 029C0A38197E226600DA6FE9 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 029C0A2E197E226600DA6FE9 /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -368,7 +293,10 @@ DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = WaterfallFlowLayout/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "com.ecerney.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = CollectionViewWaterfallLayoutDemo; SWIFT_VERSION = 5.0; @@ -382,48 +310,13 @@ DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = WaterfallFlowLayout/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.ecerney.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = CollectionViewWaterfallLayoutDemo; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 029C0A45197E226600DA6FE9 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", + LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", + "@executable_path/Frameworks", ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = WaterfallFlowLayoutTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.ecerney.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = CollectionViewWaterfallLayoutDemo; SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CollectionViewWaterfallLayoutDemo.app/CollectionViewWaterfallLayoutDemo"; - }; - name = Debug; - }; - 029C0A46197E226600DA6FE9 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); - INFOPLIST_FILE = WaterfallFlowLayoutTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.ecerney.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = CollectionViewWaterfallLayoutDemo; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CollectionViewWaterfallLayoutDemo.app/CollectionViewWaterfallLayoutDemo"; }; name = Release; }; @@ -448,16 +341,14 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 029C0A44197E226600DA6FE9 /* Build configuration list for PBXNativeTarget "CollectionViewWaterfallLayoutDemoTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 029C0A45197E226600DA6FE9 /* Debug */, - 029C0A46197E226600DA6FE9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + 30F6564A2591EF8C005EFF4B /* CollectionViewWaterfallLayout */ = { + isa = XCSwiftPackageProductDependency; + productName = CollectionViewWaterfallLayout; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 029C0A1D197E226600DA6FE9 /* Project object */; } diff --git a/WaterfallDemo/WaterfallFlowLayout/ViewController.swift b/WaterfallDemo/WaterfallFlowLayout/ViewController.swift index e782abb..90954ad 100644 --- a/WaterfallDemo/WaterfallFlowLayout/ViewController.swift +++ b/WaterfallDemo/WaterfallFlowLayout/ViewController.swift @@ -7,6 +7,7 @@ // import UIKit +import CollectionViewWaterfallLayout class ViewController: UIViewController { @@ -27,7 +28,7 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let layout = CollectionViewWaterfallLayout() + let layout = CollectionViewWaterfallLayout(delegate: self) layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) layout.headerInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0) layout.headerHeight = 50 diff --git a/WaterfallDemo/WaterfallFlowLayoutTests/Info.plist b/WaterfallDemo/WaterfallFlowLayoutTests/Info.plist deleted file mode 100644 index 6d32c15..0000000 --- a/WaterfallDemo/WaterfallFlowLayoutTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/WaterfallDemo/WaterfallFlowLayoutTests/WaterfallFlowLayoutTests.swift b/WaterfallDemo/WaterfallFlowLayoutTests/WaterfallFlowLayoutTests.swift deleted file mode 100644 index 73075c1..0000000 --- a/WaterfallDemo/WaterfallFlowLayoutTests/WaterfallFlowLayoutTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// WaterfallFlowLayoutTests.swift -// WaterfallFlowLayoutTests -// -// Created by Eric Cerney on 7/21/14. -// Copyright (c) 2014 Eric Cerney. All rights reserved. -// - -import UIKit -import XCTest - -class WaterfallFlowLayoutTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - XCTAssert(true, "Pass") - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure() { - // Put the code you want to measure the time of here. - } - } - -}