{"id":3055,"url":"https://github.com/marty-suzuki/DuctTape","last_synced_at":"2025-08-06T16:31:58.292Z","repository":{"id":50579206,"uuid":"212170594","full_name":"marty-suzuki/DuctTape","owner":"marty-suzuki","description":"📦 KeyPath dynamicMemberLookup based syntax sugar for Swift.","archived":false,"fork":false,"pushed_at":"2021-06-03T01:49:06.000Z","size":21,"stargazers_count":177,"open_issues_count":0,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-26T01:34:51.489Z","etag":null,"topics":["carthage","cocoapods","ios","keypath-dynamicmemberlookup","macos","swift","swift-package-manager","syntax-sugar","tvos","watchos"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marty-suzuki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-01T18:31:52.000Z","updated_at":"2024-11-22T12:45:01.000Z","dependencies_parsed_at":"2022-08-24T01:40:15.527Z","dependency_job_id":null,"html_url":"https://github.com/marty-suzuki/DuctTape","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marty-suzuki%2FDuctTape","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marty-suzuki%2FDuctTape/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marty-suzuki%2FDuctTape/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marty-suzuki%2FDuctTape/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marty-suzuki","download_url":"https://codeload.github.com/marty-suzuki/DuctTape/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228923739,"owners_count":17992572,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carthage","cocoapods","ios","keypath-dynamicmemberlookup","macos","swift","swift-package-manager","syntax-sugar","tvos","watchos"],"created_at":"2024-01-05T20:16:30.109Z","updated_at":"2024-12-09T16:31:15.452Z","avatar_url":"https://github.com/marty-suzuki.png","language":"Swift","funding_links":[],"categories":["Utility","Libs","Utility [🔝](#readme)"],"sub_categories":["Web View","Utility"],"readme":"# DuctTape\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://travis-ci.org/marty-suzuki/DuctTape\"\u003e\u003cimg alt=\"CI Status\" src=\"https://img.shields.io/travis/marty-suzuki/DuctTape.svg?style=flat\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/DuctTape\"\u003e\u003cimg alt=\"Pod\" src=\"https://img.shields.io/cocoapods/v/DuctTape.svg?style=flat\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\u003cimg alt=\"Carthage\" src=\"https://img.shields.io/badge/Carthage-compatible-yellow.svg\"/\u003e\u003c/a\n\u003ca href=\"https://swift.org/package-manager\"\u003e\u003cimg alt=\"SwiftPM\" src=\"https://img.shields.io/badge/SwiftPM-compatible-green.svg\"/\u003e\u003c/a\u003e\n\u003cbr/\u003e\n\u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg alt=\"Swift5\" src=\"https://img.shields.io/badge/language-Swift5-orange.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/DuctTape\"\u003e\u003cimg alt=\"Platform\" src=\"https://img.shields.io/cocoapods/p/DuctTape.svg?style=flat\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/DuctTape\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/cocoapods/l/DuctTape.svg?style=flat\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n📦 KeyPath dynamicMemberLookup based syntax sugar for Swift.\n\n```swift\nlet label: UILabel = UILabel().ductTape\n    .numberOfLines(0)\n    .textColor(.red)\n    .text(\"Hello, World!!\")\n```\n\nAbove is same as below definition.\n\n```swift\nlet label: UILabel = {\n    let label = UILabel()\n    label.numberOfLines = 0\n    label.textColor = .red\n    label.text = \"Hello, World!!\"\n    return label\n}()\n```\n\n## Usage\n\nNSObject already has been compatible with DuctTape, so you can access `.ductTape` property like below.\n\n```swift\nlet builder: Builder\u003cUIView\u003e = UIView().ductTape\n```\n\nIf you access `.ductTape`, it returns `Builder` that provides setter of properties via KeyPath dynamicMemberLookup.\n\n```swift\nlet view: UIView = UIView().ductTape\n    .backgroundColor(.red)\n    .translatesAutoresizingMaskIntoConstraints(false)\n```\n\n#### How to access methods\n\nIf you want to access methods of object which is building, `func reinforce(_ handler: (Base) -\u003e Void) Builder\u003cBase\u003e` enable to access methods.\n\n```swift\nlet collectionView: UICollectionView = UICollectionView().ductTape\n    .backgroundColor(.red)\n    .reinforce { collectionView in\n        collectionView.register(UITableViewCell.self, forCellWithReuseIdentifier: \"Cell\")\n    }\n```\n\n`Builder` has `func reinforce\u003cT1, ...\u003e(_ t1: T1, ..., handler: (Base) -\u003e Void) Builder\u003cBase\u003e` methods.\nIn additional usage, be able to access outside object with `func reinforce` if passing objects as arguments.\n\n```swift\nlazy var collectionView: UICollectionView = UICollectionView().ductTape\n    .translatesAutoresizingMaskIntoConstraints(false)\n    .reinforce(view) { collectionView, view in\n        view.addSubview(collectionView)\n        NSLayoutConstraint.activate([\n            view.topAnchor.constraint(equalTo: collectionView.topAnchor),\n            view.leadingAnchor.constraint(equalTo: collectionView.leadingAnchor),\n            view.trailingAnchor.constraint(equalTo: collectionView.trailingAnchor),\n            view.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)\n        ])\n    }\n```\n\n#### How to use DuctTape with self-implemented classes\n\nThere are two ways to use DuctTape.\n\n1. Use DuctTapeCompatible\n\n```swift\nclass Dog: DuctTapeCompatible {\n    var name: String\n}\n\nlet dog: Dog = Dog().ductTape\n    .name(\"Copernicus\")\n```\n\n2. Use Builder directly\n\n```swift\nclass Dog {\n    var name: String\n}\n\nlet dog: Dog = Builder(Dog())\n    .name(\"Copernicus\")\n```\n\n#### Sample Code\n\n```swift\nclass ViewController: UIViewController {\n\n    let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()\n        .ductTape\n        .minimumLineSpacing(10)\n        .minimumInteritemSpacing(10)\n        .itemSize(CGSize(width: 100, height: 100))\n        .scrollDirection(.vertical)\n\n    lazy var collectionView: UICollectionView = UICollectionView(frame: .zero,\n                                                                 collectionViewLayout: flowLayout)\n        .ductTape\n        .dataSource(self)\n        .delegate(self)\n        .translatesAutoresizingMaskIntoConstraints(false)\n        .reinforce {\n            $0.register(UICollectionViewCell.self, forCellWithReuseIdentifier: \"Cell\")\n        }\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        view.addSubview(collectionView)\n        NSLayoutConstraint.activate([\n            view.topAnchor.constraint(equalTo: collectionView.topAnchor),\n            view.leadingAnchor.constraint(equalTo: collectionView.leadingAnchor),\n            view.trailingAnchor.constraint(equalTo: collectionView.trailingAnchor),\n            view.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)\n        ])\n    }\n}\n```\n\n## Requirement\n\n- Xcode 11\n- macOS 10.10\n- iOS 9.0\n- tvOS 10.0\n- watchOS 3.0\n\n## Installation\n\n#### CocoaPods\n\nDuctTape is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your `Podfile`:\n\n```ruby\npod \"DuctTape\"\n```\n\n#### Carthage\n\nIf you’re using [Carthage](https://github.com/Carthage/Carthage), simply add\nDuctTape to your `Cartfile`:\n\n```\ngithub \"marty-suzuki/DuctTape\"\n```\n\n#### Swift Package Manager\n\nSimply add the following line to your `Package.swift`:\n\n```\n.package(url: \"https://github.com/marty-suzuki/DuctTape.git\", from: \"version\")\n```\n\n## License\n\nDuctTape is released under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarty-suzuki%2FDuctTape","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarty-suzuki%2FDuctTape","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarty-suzuki%2FDuctTape/lists"}