{"id":22050134,"url":"https://github.com/icapps/ios-stella","last_synced_at":"2026-01-28T12:09:46.726Z","repository":{"id":48769741,"uuid":"60535172","full_name":"icapps/ios-stella","owner":"icapps","description":"All our utilities bundles into the Stella cocoapod.","archived":false,"fork":false,"pushed_at":"2023-06-28T12:47:05.000Z","size":12803,"stargazers_count":1,"open_issues_count":4,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-12-26T16:51:22.317Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/icapps.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-06-06T14:36:13.000Z","updated_at":"2021-03-26T10:45:01.000Z","dependencies_parsed_at":"2025-05-08T23:10:56.153Z","dependency_job_id":"b62199ac-f368-403b-8a7d-4ca2c1339c84","html_url":"https://github.com/icapps/ios-stella","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/icapps/ios-stella","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Fios-stella","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Fios-stella/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Fios-stella/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Fios-stella/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icapps","download_url":"https://codeload.github.com/icapps/ios-stella/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icapps%2Fios-stella/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28845107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T10:53:21.605Z","status":"ssl_error","status_checked_at":"2026-01-28T10:53:20.789Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":[],"created_at":"2024-11-30T14:17:59.078Z","updated_at":"2026-01-28T12:09:46.711Z","avatar_url":"https://github.com/icapps.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](./Images/StellaShield.jpg)\n\n[![CI Status](http://img.shields.io/travis/icapps/ios-stella.svg?style=flat)](https://travis-ci.org/icapps/ios-stella)\n[![License](https://img.shields.io/cocoapods/l/Stella.svg?style=flat)](http://cocoapods.org/pods/Stella)\n[![Platform](https://img.shields.io/cocoapods/p/Stella.svg?style=flat)](http://cocoapods.org/pods/Stella)\n[![Language Swift 4.0](https://img.shields.io/badge/Language-Swift%204.2-orange.svg?style=flat)](https://swift.org)\n\n\u003e Stella contains a set of utilities that can be used during iOS development in Swift.\n\n## TOC\n\n- [Installation](#installation)\n  - [Swift Package Manager](#swift-package-manager)\n  - [Cocoapods](#cocoapods)\n  - [Carthage](#carthage)\n- [Features](#features)\n  - [Defaults](#defaults)\n  - [Keychain](#keychain)\n  - [Localization](#localization)\n  - [Extensions](#extensions)\n    - [Array](#array)\n    - [Bundle+Versions](#bundleversions)\n    - [CALayer+Shadow](#calayershadow)\n    - [CGFloat+Radians](#cgfloatradians)\n    - [UIView+Responder](#uiviewresponder)\n    - [UICollectionView+Reuse](#uicollectionviewreuse)\n    - [UITableView+Reuse](#uitableviewreuse)\n    - [UIView+Constraints](#uiviewconstraints)\n    - [UIView+Nib](#uiviewnib)\n    - [UIViewController+Child](#uiviewcontrollerchild)\n    - [UIViewController+Storyboard](#uiviewcontrollerstoryboard)\n    - [UIViewController+TopMost](#uiviewcontrollertopmost)\n    - [Optionals](#optionals)\n- [Contribute](#contribute)\n  - [How to contribute?](#howtocontribute)\n  - [Contributors](#contributors)\n- [License](#license)\n\n## Installation 💾\n\n## Swift Package Manager\n\nYou can install `Stella` using the Swift Package Manager. This is available starting from Xcode 11. Just search for `icapps/ios-stella` and install it.\n\n### Cocoapods\n\nStella is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your `Podfile`:\n\n```ruby\npod 'Stella', git: 'https://github.com/icapps/ios-stella.git', commit: '...'\n```\n\n_Pass the correct commit reference to make sure your code doesn't break in future updates._\n\n### Carthage\n\nTo integrate Stella into your Xcode project using Carthage, specify it in your `Cartfile`\"\n\n```ruby\ngithub \"icapps/ios-stella\" ~\u003e 1.5.1\n```\n\nThen, run the following command to build the Stella framework:\n\n```sh\ncarthage update\n```\n\nPerform the additional steps in orde the get Carthage setup with this framework: [Carthage's README](https://github.com/Carthage/Carthage#getting-started)\n\n## Features\n\n### Defaults\n\nWe have a cleaner way to use `NSUserDefaults`. Define the user defaults by extending the `DefaultsKeys` class.\n\n```swift\nextension DefaultsKeys {\n  // Writes a string object to the defaults with the 'stringValue' key.\n  static let stringValue = DefaultsKey\u003cString?\u003e(\"stringValue\")\n  // Writes an integer to the defaults with the 'integerValue' key.\n  static let integerValue = DefaultsKey\u003cInt?\u003e(\"integerValue\")\n  // Writes a double to the defaults with the 'doubleValue' key.\n  static let doubleValue = DefaultsKey\u003cDouble?\u003e(\"doubleValue\")\n  // Writes a float to the defaults with the 'floatValue' key.\n  static let floatValue = DefaultsKey\u003cFloat?\u003e(\"floatValue\")\n  // Writes a bool to the defaults with the 'booleanValue' key.\n  static let booleanValue = DefaultsKey\u003cBool?\u003e(\"booleanValue\")\n  // Writes a date object to the defaults with the 'dateValue' key.\n  static let dateValue = DefaultsKey\u003cNSDate?\u003e(\"dateValue\")\n  // Writes a dictionary object to the defaults with the 'dictValue' key.\n  static let dictValue = DefaultsKey\u003c[String: Any]?\u003e(\"dictValue\")\n}\n```\n\nYou can read/write the from/to the `NSUserDefaults` by using the `subscript` on the `Defaults` class.\n\n```swift\nDefaults[.stringValue] = \"A string value\"\nprint(Defaults[.stringValue]) // Prints 'A string value'\n\nDefaults[.integerValue] = 123\nprint(Defaults[.integerValue]) // Prints '123'\n\nDefaults[.doubleValue] = 123.123\nprint(Defaults[.doubleValue]) // Prints '123.123'\n\nDefaults[.floatValue] = 123.321\nprint(Defaults[.floatValue]) // Prints '123.312'\n\nDefaults[.booleanValue] = true\nprint(Defaults[.booleanValue]) // Prints 'true'\n\nDefaults[.dateValue] = NSDate()\nprint(Defaults[.dateValue]) // Prints '1996-12-19T16:39:57-08:00'\n\nDefaults[.dictValue] = [\"SomeKey\" : \"SomeValue\"]\nlet value = Defaults[.dictValue]\nprint(value[\"SomeKey\"]) // Prints 'SomeValue'\n```\n\n### Keychain\n\nWe have a cleaner way to use the `Keychain`. Define the user defaults by extending the `Keys` class.\n\n```swift\nextension Keys {\n  // Writes a string object to the keychain with the 'stringValue' key.\n  static let stringValue = Key\u003cString?\u003e(\"stringValue\")\n}\n```\n\nYou can read/write the from/to the `Keychain` by using the `subscript` on the `Keychain` class.\nIt supports both regular `String` values as well as `Codable` objects.\n\n```swift\nKeychain[.stringValue] = \"A string value\"\nprint(Keychain[.stringValue]) // Prints 'A string value'\n\n```swift\nKeychain[.codableValue] = ClassConformingToCodable()\nprint(Keychain[.codableValue]) // Prints '\u003cClassConformingToCodable: 0x0123456789\u003e'\n```\n```\n\nIn some cases you want to be able to set additional keychain query paramaters on an item.\n\n```swift\nstatic let noBackupValue = Key\u003cString?\u003e(\"noBackup\", {\n  return [kSecAttrAccessible as String: kSecAttrAccessibleAlwaysThisDeviceOnly]\n}())\n```\n\n### Localization\n\nLocalize a key in no time with this handy localization function.\n\n```swift\nlet key = \"this_is_your_localization_key\"\nprint(key.localizedString)\n// The debug console will print the localized\n// string found in your .strings file.\n```\n\n### Extensions\n\n#### Array\n\nFetch an element from an array that could possible be out of bounds.\n\n```swift\nlet array = [1, 2, 3, 4]\narray[safe: 2] // Returns 3\narra[safe: 10] // Returns nil\n```\n\nReturns the array with a limited subset starting from the front/rear.\n\n```swift\nlet array = [1, 2, 3, 4]\narray.truncate(by: 2) // Returns [1, 2]\narray.reverseTruncate(by: 2) // Returns [3, 4]\n```\n\nReturns if an element is found in an array.\n\n```swift\nlet array = [1, 2, 3, 4]\narray.contains(2) // Returns true\narray.contains(10) // Returns false\n```\n\nReturns an array with unique values depending on the `Hashable` value.\n\n```swift\nlet array = [1, 2, 3, 2, 4, 1]\narray.unique // Returns [1, 2, 3, 4]\n```\n\nRemove an element from an array and returns the removed index.\n\n```swift\nvar array = [1, 2, 3, 4]\narray.remove(3) // Returns 2\narray // Mutated to [1, 2, 4]\n```\n\n#### Bundle+Versions\n\nGet the marketing and build version quickly from the bundle.\n\n```swift\nlet bundle = Bundle.main\nbundle.shortVersionString // Returns 1.2.3\nbundle.bundleVersion // Returns 1 (the build version)\n```\n\n#### CALayer+Shadow\n\nQuickly add a shadow around a certain view\n\n```swift\nlet view = UIView()\nview.layer.applyShadow()\n\nlet customShadowView = UIView()\ncustomShadowView.layer.applyShadow(color: .red, opacity: 0.2, x: 0, y: 4, blur: 10, spread: 0)\n```\n\nQuickly remove a shadow from a certain view\n\n```swift\nlet view = UIView()\nview.layer.removeShadow()\n```\n\n#### CGFloat+Radians\n\nConvert from degrees to radians and vice versa.\n\n```swift\nCGFloat(180).degreesToRadians // Returns .pi\nCGFloat.pi.radiansToDegrees // Returns 180.0\n```\n\n#### UIView+Responder\n\nGet the `UIViewController` that manages your view.\n\n```swift\nlet controller = UIViewController()\ncontroller.view.respondingController // Returns the controller instance.\n```\n\n#### UICollectionView+Reuse\n\nRegister and reuse cells in a type safe way.\n\n```swift\n// Register a cell from a nib with the same name.\ncollectionView.register(CustomCollectionViewCell.self)\n\n// Register a reusable view from a nib with the same name.\ncollectionView.register(CustomReusableView.self, forSupplementaryViewOfKind: \"Some\")\n\n// Dequeue a cell of type CustomCollectionViewCell\ncollectionView.dequeueReusableCell(for: indexPath) as CustomCollectionViewCell\n\n// Dequeue a reusable view of type CustomReusableView\ncollectionView.dequeueReusableSupplementaryView(ofKind: \"Some\", for: indexPath) as CustomReusableView\n```\n\n#### UITableView+Reuse\n\nRegister and reuse cells in a type safe way.\n\n```swift\n// Register a cell from a nib with the same name.\ntableView.register(CustomTableViewCell.self)\n\n// Register a footer view from a nib with the same name.\ntableView.registerHeaderFooter(CustomFooterView.self)\n\n// Dequeue a cell of type CustomTableViewCell\ntableView.dequeueReusableCell(forIndexPath: indexPath) as CustomTableViewCell\n\n// Dequeue a cell of type CustomTableViewCell with a custom identifier.\ntableView.dequeueReusableCell(forIdentifier: \"identifier\") as CustomTableViewCell\n\n// Dequeue a header view of type CustomReusableView with a custom identifier.\ntableView.dequeueReusableHeaderFooter(forIdentifier: \"identifier\") as CustomReusableView\n\n// Dequeue a header view of type CustomReusableView.\ntableView.dequeueReusableHeaderFooter(forIdentifier: \"identifier\") as CustomReusableView\n\n// Get the types cell for row.\ntableView.cellForRow(at: indexPath) as CustomTableViewCell\n```\n\n#### UIView+Constraints\n\nConstraint a subview quickly to the bounds of the superview.\n\n_Optionally you can add insets that set some spacing inside the view._\n\n```swift\nview.constraint(to: superview)\nview.constraint(to: superview, insets: .zero)\n\n// Same as above but take safe area's into account.\nview.constraint(to: superview, safeAreaInsets: .zero)\n```\n\n#### UIView+Nib\n\nGet access to reuse identifiers.\n\n```swift\n// Return the name of the view's class as it's reuse identifier.\nUIView.reuseIdenfier\n\n// Return the name of the view's class as it's nib name.\nUIView.nibName\n\n// Return the nib matching the class name of the view.\nUIView.nib\n```\n\nLoad the `UIView` from a nib with the same name.\n\n_It is important to type the destination property in orde to load the correct nib._\n\n```swift\nlet view: SomeView = UIView.loadFromNib()\n```\n\n#### UIViewController+Child\n\nEasily add and remove a controller as a childViewController.\n\n_Optionally you can add insets that set some spacing inside the container view._\n\n```swift\n// Add the controller to the container view, pin it and handle the containment correctly.\nrootController.add(childController: controller, to: containerView)\nrootController.add(childController: controller, to: containerView, insets: .zero)\n\n// Add the same child controller as above, but take the safe area's into account.\nrootController.add(childController: controller, to: containerView, safeAreaInsets: .zero)\n\n// Remove the controller and handle the containtment correctly.\nrootController.remove(childController: controller)\n```\n\n#### UIViewController+Storyboard\n\nLoad the view controller directly from a storyboard.\n\n```swift\n// Load the initial controller from the storyboard.\nlet controller = SomeController.from(storyboard: \"StoryboardName\")\n\n// Pass a custom bundle to load from.\nlet controller = SomeController.from(storyboard: \"StoryboardName\", bundle: CustomBundle())\n\n// Load a controller with the given storyboard identifier.\nlet controller = SomeController.from(storyboard: \"StoryboardName\", identifier: \"SomeControllerIdentifier\")\n```\n\n#### UIViewController+TopMost\n\nGet the `UIViewController` that is currently presented on top of the application. It doesn't matter if a `UINavigationController` or a `UITabBarController` is in play or not.\n\n```swift\nlet controller = UIAlertController(...)\n\n// Present an alert an top of all the controllers.\notherController.topMostViewController.present(controller, animated: false, completion: nil)\n```\n\n#### Optionals\n\nAdded soms easy to used optional intializers.\n\n```swift\nURL(string: nil)\nUIImage(data: nil)\n```\n\n## Contribute\n\n### How to contribute ❓\n\n1. Add a Github issue describing the missing functionality or bug.\n2. Implement the changes according to the `Swiftlint` coding guidelines.\n3. Make sure your changes don't break the current version. (`deprecate` is needed)\n4. Fully test the added changes.\n5. Send a pull-request.\n\n### Contributors 🤙\n\n- Jelle Vandebeeck, [@fousa](https://github.com/fousa)\n- Dylan Gyesbreghs, [@dgyesbreghs](https://github.com/dgyesbreghs)\n- Hans Van Herreweghe, [@herre](https://github.com/herre)\n- Hannes Van den Berghe, [@HannesVDB](https://github.com/HannesVDB)\n- Alain Hufkens, [@hufkens](https://github.com/HannesVDB)\n- Stijn Willems, [@doozMen](https://github.com/doozMen)\n\n## License\n\nStella is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficapps%2Fios-stella","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficapps%2Fios-stella","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficapps%2Fios-stella/lists"}