{"id":3007,"url":"https://github.com/hyperoslo/Sugar","last_synced_at":"2025-08-06T16:32:06.615Z","repository":{"id":34823032,"uuid":"38810470","full_name":"hyperoslo/Sugar","owner":"hyperoslo","description":":coffee: Something sweet that goes great with your Cocoa","archived":false,"fork":false,"pushed_at":"2020-06-18T11:12:48.000Z","size":307,"stargazers_count":1068,"open_issues_count":0,"forks_count":69,"subscribers_count":37,"default_branch":"master","last_synced_at":"2024-12-07T21:44:24.999Z","etag":null,"topics":["ios","sugar","sweet","swift"],"latest_commit_sha":null,"homepage":"https://github.com/hyperoslo","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hyperoslo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-09T09:10:55.000Z","updated_at":"2024-12-07T02:55:02.000Z","dependencies_parsed_at":"2022-08-30T15:11:22.447Z","dependency_job_id":null,"html_url":"https://github.com/hyperoslo/Sugar","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperoslo%2FSugar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperoslo%2FSugar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperoslo%2FSugar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hyperoslo%2FSugar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hyperoslo","download_url":"https://codeload.github.com/hyperoslo/Sugar/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228923758,"owners_count":17992574,"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":["ios","sugar","sweet","swift"],"created_at":"2024-01-05T20:16:28.785Z","updated_at":"2024-12-09T16:31:20.107Z","avatar_url":"https://github.com/hyperoslo.png","language":"Swift","funding_links":[],"categories":["Utility","Libs","Swift","Extensions","Utilities and Extensions","Utility [🔝](#readme)"],"sub_categories":["Web View","Utility","Other free courses"],"readme":"# Sugar\n\nSugar is a sweetener for your Cocoa implementations.\n\n[![CI Status](https://circleci.com/gh/hyperoslo/Sugar.png)](https://circleci.com/gh/hyperoslo/Sugar)\n[![Version](https://img.shields.io/cocoapods/v/Sugar.svg?style=flat)](http://cocoadocs.org/docsets/Sugar)\n[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![License](https://img.shields.io/cocoapods/l/Sugar.svg?style=flat)](http://cocoadocs.org/docsets/Sugar)\n[![Platform](https://img.shields.io/cocoapods/p/Sugar.svg?style=flat)](http://cocoadocs.org/docsets/Sugar)\n![Swift](https://img.shields.io/badge/%20in-swift%205.0-orange.svg)\n\nTable of Contents\n--\n\n\u003cimg src=\"https://raw.githubusercontent.com/hyperoslo/Sugar/master/Images/icon.png\" alt=\"Hue Icon\" align=\"right\" /\u003e\n\n\u003c!-- TOC depthFrom:2 depthTo:4 withLinks:1 updateOnSave:1 orderedList:0 --\u003e\n\n- [iOS](#ios)\n\t- [Application](#application)\n\t- [Screen](#screen)\n\t- [Simulator](#simulator)\n\t- [Keyboard Observer](#keyboard-observer)\n\t- [iOS Extensions](#ios-extensions)\n\t\t- [UIView](#uiview)\n\t\t- [UIImage](#uiimage)\n- [OS X](#os-x)\n\t- [OS X Extensions](#os-x-extensions)\n\t\t- [NSTableView](#nstableview)\n- [Shared](#shared)\n\t- [Dates](#dates)\n\t\t- [Compare](#compare)\n\t\t- [Construct](#construct)\n\t- [Frame](#frame)\n\t- [Grand Central Dispatch](#grand-central-dispatch)\n\t- [Localization](#localization)\n\t- [Once](#once)\n\t- [Operators](#operators)\n\t- [Range](#range)\n\t- [Regex](#regex)\n\t- [Shared Extensions](#shared-extensions)\n\t\t- [+Queueable](#queueable)\n\t\t- [URLStringConvertible](#urlstringconvertible)\n\t\t- [Core Foundation](#core-foundation)\n\t- [Swizzler](#swizzler)\n\t- [Then](#then)\n\t- [Type Alias](#type-alias)\n\t- [UITesting](#uitesting)\n\t- [UnitTesting](#unittesting)\n- [Installation](#installation)\n- [Author](#author)\n- [License](#license)\n\n\u003c!-- /TOC --\u003e\n\n## iOS\n\n### Application\n\n```swift\nlet appName = Application.name             // CFBundleDisplayName : String\nlet appVersion = Application.version       // CFBundleShortVersionString : String\nlet appExecutable = Application.executable // CFBundleExecutable : String\nlet appBundle = Application.bundle         // CFBundleIdentifier : String\nlet appSchemes = Application.schemes       // CFBundleURLSchemes : [String]\nlet mainAppScheme = Application.mainScheme // CFBundleURLSchemes.first : String?\n```\n\nGain easy access to main bundle information.\n\n### Screen\n\n```swift\nlet pixelSize = Screen.pixelSize // CGSize(width: screenWidth * scale, height: screenHeight * scale)\n```\n\nGet the actual pixel information of the device screen.\n\n### Simulator\n\n```swift\nif !Simulator.isRunning {\n  // add device specific operations here\n}\n```\n\nTo easily exclude operations from when you as a developer runs the application in the simulator,\nnot subscribing to push notification or running analytics operations etc.\n\n### Keyboard Observer\n\nObserve keyboard showing and hiding events, and handle it\n\n```swift\nlet handler = BasicKeyboardHandler()\nhandler.show = { [weak self] height in\n  // move text fields up\n}\n\nhandler.hide = { [weak self] in\n  // move text fields back to original position\n}\n\nkeyboardObserver = KeyboardObserver(handler: handler)\n```\n\nCurrently support\n\n- BasicKeyboardHandler: basic UIView animation\n- InsetKeyboardHandler: animate UIScrollView insets\n- ConstraintKeyboardHandler: animate bottom layout constraint\n- CustomKeyboardHandler: custom handling\n\n### iOS Extensions\n\n#### UIView\n\n##### .optimize()\n```swift\nlet view = UIView.optimize\n/*\n  clipsToBounds = true\n  layer.drawsAsynchronously = true\n  opaque = true\n*/\n```\n\n#### UIImage\n\n##### +Rendering mode\n\n```swift\nimage.original // imageWithRenderingMode(.AlwaysOriginal)\nimage.template // imageWithRenderingMode(.AlwaysTemplate)\n```\n\n## Shared\n\n### SequenceType\n\n```swift\nlet first: Int? = items.findFirst({ $0 \u003e 10 })\n```\n\n### Dates\n\n#### Compare\n\n```swift\nif date1 \u003c date2 {\n  // do something\n} else if date1 \u003e= date2 {\n  // do something else\n}\n```\n\n#### Construct\n\n```swift\nlet _ = 5.day\nlet _ = 3.week\n```\n\n### Frame\n\n```swift\nlet view = UIView()\nview.width = 200\nview.height = 200\nview.x = 25\nview.y = 25\n\nprint(view.width) // prints 200\nprint(view.height) // prints 200\nprint(view.x) // prints 25\nprint(view.y) // prints 25\n```\n\n### Grand Central Dispatch\n\n```swift\ndispatch {\n  // dispatch in main queue\n}\n\ndispatch(queue: .Background) {\n  // dispatch in background queue\n}\n\nlazy var serialQueue = dispatch_queue_create(\"serialQueue\", DISPATCH_QUEUE_SERIAL)\ndispatch(queue: .Custom(serialQueue)) {\n  // dispatch in a serial queue\n}\n```\n\nEasy dispatching with grand central dispatch.\nSupport all the regular global queues: `Main`, `Interactive`, `Initiated`, `Utility`, `Background`.\nAnd `.Custom()` for your own dispatch queues.\n\n### Localization\n\n```swift\nlet string = localizedString(\"My Profile\")\nlet formattedString = localizedString(key: \"%d numbers\", arguments: 10)\n```\n\nSwift access (pun intended) to `NSLocalizedString`, you will get more valid auto completion\nwith this one, we promise.\n\n### Once\n\n```swift\nlet once = Once()\nonce.run {\n  // do something\n}\n\nonce.run {\n  // no effect\n}\n```\n\n### Operators\n\n```swift\nvar url = NSURL(string: \"hyper.no\")!\nurl ?= NSURL(string: \"\\\\/http\")\n// url is equal to hyper.no\n```\n\nThe `?=` only assigns values if the right is not nil.\n\n### Range\n\n```swift\nlet acceptable = 200..\u003c300\nif acceptable.contains(response.statusCode) {\n  // Status code is between 200 and 299.\n}\n```\n\n### Regex\n\n```swift\nif \"ios@hyper.no\".isEmail() {\n  // Is email\n}\n\nlet stringNumber = \"1984\"\nif stringNumber.isNumber() {\n  // Is a number\n}\n\nif stringNumber.matches(\"^[0-9]+$\") {\n  // Is a number\n}\n```\n\n### Shared Extensions\n\n#### +Queueable\n\n```swift\n\nstruct Object: Queueable {\n\n  func process() -\u003e Bool { return true }\n}\n\nlet myQueue = [Object(), Object()]\nmyQueue.processQueue()\n```\n\nMake your own processing queue with ease, just make your object conform the `Queueable`.\n\n```swift\npublic protocol Queueable {\n  func process() -\u003e Bool\n}\n```\n\n#### URLStringConvertible\n\n```swift\nlet urlString = \"https://hyper.no\"\nlet url = urlString.url\n```\n\nHighly inspired by / borrowed from [Alamofire](https://github.com/Alamofire/Alamofire)'s [implementation](https://github.com/Alamofire/Alamofire/blob/990fded98afe5135dc418e1f6eb0287027dd067f/Source/Alamofire.swift#L31) of URLStringConvertible.\n\n#### Core Foundation\n\n```swift\nlet string = \"hyper/oslo\"\nstring.length // 10\nstring.truncate(5) // hyper...\nstring.split(/) // [\"hyper\", oslo]\n\nif string.isPresent {\n  // do something\n}\n\nif string.contains(\"hyper\") {\n  // found hyper\n}\n\nvar dirtyString = \"   hyper   \"\nprint(dirtyString.trim()) // prints \"hyper\"\n```\n\nJust some extra sugar on top of `String` for getting the length, truncating, trimming or splitting a `String`.\n\n`isPresent` is the opposite of `isEmpty`.\n\n`contains` and be used to check if a string contains a word or pharse.\n\n### Swizzler\n\n```swift\nclass Swizzled: NSObject {\n\n  override class func initialize() {\n    struct Static {\n      static var token: dispatch_once_t = 0\n    }\n\n    if self !== Swizzled.self {\n    return\n  }\n\n  dispatch_once(\u0026Static.token) {\n    Swizzler.swizzle(\"method\", cls: self)\n  }\n}\n\n  dynamic func method() -\u003e Bool {\n    return true\n  }\n\n  func swizzled_method() -\u003e Bool {\n    return false\n  }\n}\n\nlet object = Swizzled()\nobject.method() // false\n```\n\nEveryday we are swizzling, this use to be mundane, now it just Swiftling, we mean, super fast.\n\n### Then\n\n```\nlet UIView().then {\n  $0.backgroundColor = UIColor.blackColor()\n}\n```\n\nThis implementation is brought to you by [@devxoul](https://github.com/devxoul) by his awesome [Then](https://github.com/devxoul/Then) repository.\n\n### Type Alias\n\n```swift\npublic typealias JSONArray = [[String : AnyObject]]\npublic typealias JSONDictionary = [String : AnyObject]\n```\n\n### UITesting\n```\nif UITesting.isRunning {\n  // tests are running\n} else {\n  // everything is fine, move along\n}\n```\n\nTo easily include or exclude operations for when you are running UI tests.\n\n### UnitTesting\n\n```\nif UnitTesting.isRunning {\n  // running test\n}\n\nfunc testPerformance() {\n  let measurement = measure {\n    // run operation\n  }\n}\n```\n\nCheck if you are running UniTests and to measure performance.\n\n## Installation\n\n**Sugar** is available through [CocoaPods](http://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'Sugar'\n```\n\n**Sugar** is also available through [Carthage](https://github.com/Carthage/Carthage).\nTo install just write into your Cartfile:\n\n```ruby\ngithub \"hyperoslo/Sugar\"\n```\n**Sugar** is also available through [Swift Package Manager](https://swift.org/package-manager).\n- iOS: Open Xcode, File-\u003eSwift Packages, search input **https://github.com/hyperoslo/Sugar.git**, and then select Version Up to Next Major **5.0.1** \u003c .\n- Or add dependencies in your `Package.swift`:\n```ruby\n.package(url: \"https://github.com/hyperoslo/Sugar.git\", .upToNextMajor(from: \"5.0.1\")),\n```\n\n## Author\n\nHyper Interaktiv AS, ios@hyper.no\n\n## License\n\n**Sugar** 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%2Fhyperoslo%2FSugar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhyperoslo%2FSugar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhyperoslo%2FSugar/lists"}