{"id":16686303,"url":"https://github.com/evermeer/stuff","last_synced_at":"2025-03-21T18:33:09.753Z","repository":{"id":54225889,"uuid":"81864474","full_name":"evermeer/Stuff","owner":"evermeer","description":"A collection of Swift code 'snippets' that are too small to create a library for and which do not fit in an other library.","archived":false,"fork":false,"pushed_at":"2023-10-13T09:55:58.000Z","size":46,"stargazers_count":41,"open_issues_count":0,"forks_count":6,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-18T03:51:29.340Z","etag":null,"topics":["codable","enum","print","swift"],"latest_commit_sha":null,"homepage":"","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/evermeer.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-13T19:49:49.000Z","updated_at":"2023-10-13T09:00:37.000Z","dependencies_parsed_at":"2024-10-28T11:29:27.134Z","dependency_job_id":"495e81a7-5531-4682-a099-cea2cdbba350","html_url":"https://github.com/evermeer/Stuff","commit_stats":{"total_commits":26,"total_committers":4,"mean_commits":6.5,"dds":0.3846153846153846,"last_synced_commit":"60df25034548427900dfe9f13518cd6c872123d9"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evermeer%2FStuff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evermeer%2FStuff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evermeer%2FStuff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evermeer%2FStuff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evermeer","download_url":"https://codeload.github.com/evermeer/Stuff/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244849341,"owners_count":20520694,"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":["codable","enum","print","swift"],"created_at":"2024-10-12T15:05:20.618Z","updated_at":"2025-03-21T18:33:09.440Z","avatar_url":"https://github.com/evermeer.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stuff\n\n[![Issues](https://img.shields.io/github/issues-raw/evermeer/Stuff.svg?style=flat)](https://github.com/evermeer/Stuff/issues)\n[![Documentation](https://img.shields.io/badge/documented-100%25-green.svg?style=flat)](http://cocoadocs.org/docsets/Stuff/)\n[![Stars](https://img.shields.io/github/stars/evermeer/Stuff.svg?style=flat)](https://github.com/evermeer/Stuff/stargazers)\n[![Downloads](https://img.shields.io/cocoapods/dt/Stuff.svg?style=flat)](https://cocoapods.org/pods/Stuff)\n\n\n[![Version](https://img.shields.io/cocoapods/v/Stuff.svg?style=flat)](http://cocoadocs.org/docsets/Stuff)\n[![Language](https://img.shields.io/badge/language-swift%203-f48041.svg?style=flat)](https://developer.apple.com/swift)\n[![Platform](https://img.shields.io/cocoapods/p/Stuff.svg?style=flat)](http://cocoadocs.org/docsets/Stuff)\n[![License](https://img.shields.io/cocoapods/l/Stuff.svg?style=flat)](http://cocoadocs.org/docsets/Stuff)\n\n[![Git](https://img.shields.io/badge/GitHub-evermeer-blue.svg?style=flat)](https://github.com/evermeer)\n[![Twitter](https://img.shields.io/badge/twitter-@evermeer-blue.svg?style=flat)](http://twitter.com/evermeer)\n[![LinkedIn](https://img.shields.io/badge/linkedin-Edwin%20Vermeer-blue.svg?style=flat)](http://nl.linkedin.com/in/evermeer/en)\n[![Website](https://img.shields.io/badge/website-evict.nl-blue.svg?style=flat)](http://evict.nl)\n[![eMail](https://img.shields.io/badge/email-edwin@evict.nl-blue.svg?style=flat)](mailto:edwin@evict.nl?SUBJECT=About%20Stuff)\n\n# General information\n\nStuff is a collection of code 'snippets' that are too small to create a library for and which do not fit in an other library. Run the unit tests to see the code in action.\n\n- [Print](#print) - For creating a nice output log\n- [Enum](#enum) - Adding functionality to an enum\n- [TODO](#todo) - Adding a TODO helper function\n- [Codable](#codable) - Adding Codable helper functions (Swift 4)\n\nTo install all parts via Swift Package Manager, add version `1.1.4` or higher with URL `https://github.com/evermeer/Stuff` to your project file. \n\n## Print\n\nYou can install this by adding the following line to your Podfile:\n\n```\npod \"Stuff/Print\"\n```\n\nThe Stuff.print function is meant to be a replacement for the standard .print function. It will give you extra information about when and where the print function was executed. Besides that there is also support for different log levels and you can specify the minimum log level that should be in the output.\n\nHere are some samples:\n\n```swift\n    Stuff.print(\"Just as the standard print but now with detailed information\")\n    Stuff.print(\"Now it's a warning\", .warn)\n    Stuff.print(\"Or even an error\", .error)\n\n    Stuff.minimumLogLevel = .error\n    Stuff.print(\"Now you won't see normal log output\")\n    Stuff.print(\"Only errors are shown\", .error)\n\n    Stuff.minimumLogLevel = .none\n    Stuff.print(\"Or if it's disabled you won't see any log\", .error)    \n```\n\nThe output of the code above is:\n\n```console\n✳️ .debug ⏱ 02/13/2017 09:52:51:852 📱 xctest [18960:?] 📂 PrintStuffTests.swift(15) ⚙️ testExample() ➡️\n    Just as the standard print but now with detailed information\n\n⚠️ .warn ⏱ 02/13/2017 09:52:51:855 📱 xctest [18960:?] 📂 PrintStuffTests.swift(16) ⚙️ testExample() ➡️\n    Now it's a warning\n\n🚫 .error ⏱ 02/13/2017 09:52:51:855 📱 xctest [18960:?] 📂 PrintStuffTests.swift(17) ⚙️ testExample() ➡️\n    Or even an error\n\n🚫 .error ⏱ 02/13/2017 09:52:51:855 📱 xctest [18960:?] 📂 PrintStuffTests.swift(21) ⚙️ testExample() ➡️\n    Only errors are shown\n```\n\nThere is also a shortcut print statement for an error object. This will print the localizedDescription and set the warning level to .error. \n```swift\n    Stuff.print(error)\n```\n\nUpdate: From now on printing .error will also give you a stacktrace.\n\nUpdate 04-04-2019 : You can now also set the minimumLogLevel to productionLogAll. This will make sure you can also see the logging in the console (menu 'Window',  'Devices and Simulators', 'Open Console') In most cases you should only use this if you want to see logging for an app that you distributed using Testflight.\n\n## Enum\n\nYou can install this by adding the following line to your Podfile:\n\n```\npod \"Stuff/Enum\"\n```\n\n- getting all possible enum values in an arry\n- getting the associated value of any enum\n- converting an array of enums with associated values to a dictionary or an query string.\n- get the raw value of an enum even it it was passed in an any\n\n\n```swift\n// You have to extend the enum with the Enum protocol (and RawEnum if you want the raw value when it's an Any)\nenum test1: String, Enum, RawEnum {\n    case option1\n    case option2\n    case option3\n}\n\nenum test2: Enum {\n    case option4(String)\n    case option5(Int)\n    case option6(Int, String)\n}\n\nXCTAssert(test1.allValues.count == 3, \"There should be 3 values\")\nfor value in test1.allValues {\n    print(\"value = \\(value)\")\n}\n\nlet v1: test2 = .option4(\"test\")\nprint(\"v1 = \\(v1.associated.label), \\(v1.associated.value!)\")\nlet v2: test2 = .option5(3)\nprint(\"v2 = \\(v2.associated.label), \\(v2.associated.value!)\")\nlet v3: test2 = .option6(4, \"more\")\nprint(\"v3 = \\(v3.associated.label), \\(v3.associated.value!)\")\n\nlet array = [v1, v2, v3]\nlet dict = [String:Any](array)\nprint(\"Array of enums as dictionary:\\n \\(dict)\")\n\nprint(\"query = \\(array.queryString))\")\n\nlet v = getRawValue(test1.option2)\nprint(\"raw value = \\(v)\")\n\nfunc getRawValue(_ value: Any) -\u003e Any {\n    return (value as? RawEnum)?.anyRawValue ?? \"\"\n}\n\n```\nThe output is:\n\n```swift\nvalue = option1\nvalue = option2\nvalue = option3\nv1 = option4, test\nv2 = option5, 3\nv3 = option6, (4, \"more\")\nArray of enums as dictionary:\n[\"option5\": 3, \"option4\": \"test\", \"option6\": (4, \"more\")]\nquery = option4=test,option5=3,option6=(4, \"more\"))\nraw value = option2\n```\n\n## TODO\n\nYou can install this by adding the following line to your Podfile:\n\n```\npod \"Stuff/TODO\"\n```\n\nWhenever you add a function to your project and postpone implementing it, you should add a TODO. \nWhenever you temporarilly change functioning code in order to debug something, you should add a TODO\nBefore commiting/pushing your code, you should evaluate/solve your TODO's\nUsually you just add a TODO comment in your code like this:\n\n```swift\n    //TODO: This needs to be fixed\n```\n\nWith the Stuff/TODO helper, you can get compile time and run time support for helping to find your TODO's. Here is an overview of the variants that you can use:\n\n```swift\n    // We need to fix something, but this code can run (compiler warning)\n    TODO()\n\n    // Now output extra info when this code is executed.\n    TODO(\"An other todo, now giving some detailed info\")\n\n    // We need to fix this. Otherwise just fail. The code will crash here. See the stacktrace,\n    TODO_\n```\n\nThe code above will put the following in your output. Besides that, you will also see depricated warnings when you have the code open in Xcode.\n\n```\n⚠️ TODO code is still in use! ⚠️\n\n⚠️ TODO code is still in use! ⚠️\nAn other todo, now giving some detailed info\nfatal error: TODO left in code: file /Users/evermeer/Desktop/dev/GitHub/Stuff/Source/TODO/TODO.swift, line 15\n```\n\nBut... It might be nicer to just add the following build phase script which will also give you compile time warnings:\n\n```\nKEYWORDS=\"TODO|FIXME|\\?\\?\\?:|\\!\\!\\!:\"\nfind \"${SRCROOT}\" \\( -name \"*.swift\" \\) -print0 | \\\nxargs -0 egrep --with-filename --line-number --only-matching \"($KEYWORDS).*\\$\" | \\\nperl -p -e \"s/($KEYWORDS)/ warning: \\$1/\"\n```\n\n## Codable\n\nYou can install this by adding the following line to your Podfile:\n\n```\npod \"Stuff/Codable\"\n```\n\nSwift 4 added the Codable (EnCodable and DeCodable) protocol which you can add to a class or struct. The swift compile will then add coding and decoding functionality to your object. With the JSONEncoder and JSONDecoder classes you can then convert an object from and to json. The Stuff Codable extension will let you do these things in a 1 liner. Here is Apple documentaion about [Codable](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) The one liners that you can use are:\n\n```swift\nlet json = yourEncodableObjectInstance.toJsonString()\nlet data = yourEncodableObjectInstance.toJsonData()\nlet newObject = try? YourCodableObject(json: json)\nlet newObject2 = try? YourCodableObject(data: data)\nlet objectArray = try? [YourCodableObject](json: json)\nlet objectArray2 = try? [YourCodableObject](data: data)\nlet newJson = objectArray.toJsonString()\nlet innerObject = try? TestCodable(json: \"{\\\"user\\\":{\\\"id\\\":1,\\\"naam\\\":\\\"Edwin\\\"}}\", keyPath: \"user\")\ntry initialObject.saveToDocuments(\"myFile.dat\")\nlet readObject = try? TestCodable(fileNameInDocuments: \"myFile.dat\")\ntry objectArray.saveToDocuments(\"myFile2.dat\")\nlet objectArray3 = try? [TestCodable](fileNameInDocuments: \"myFile2.dat\")\n```\n\nAnd here you can see how you can use these Stuff/Codable functions:\n\n```swift\nfunc test() {\n   let initialObject = TestCodable(naam: \"Edwin\", id: 1, testField: \"tst\")\n\n   guard let json = initialObject.toJsonString() else {\n      print(\"Could not create json from object\")\n      return\n   }\n   print(\"Json string of object = \\n\\t\\(json)\")\n\n   guard let newObject = try? TestCodable(json: json) else {\n      print(\"Could not create object from json\")\n      return\n   }\n   print(\"Object created with json = \\n\\t\\(newObject)\")\n   \n   let json2 = \"[{\\\"id\\\":1,\\\"naam\\\":\\\"Edwin\\\"},{\\\"id\\\":2,\\\"naam\\\":\\\"Vermeer\\\"}]\"\n   guard let array = try? [TestCodable](jsonArray: json2) else {\n      print(\"Could not create object array from json\")\n      return\n   }\n   print(\"Object array created with json = \\(array)\")\n   \n   let newJson = array.toJsonString()\n   print(\"Json from object array = \\n\\t\\(newJson)\")\n   \n   guard let innerObject = try? TestCodable(json: \"{\\\"user\\\":{\\\"id\\\":1,\\\"naam\\\":\\\"Edwin\\\"}}\", keyPath: \"user\") else {\n      print(\"Could not create object from json\")\n      return\n   }\n   print(\"inner object from json \\(String(describing: innerObject))\")\n   \n   guard let custom = try TestCodable(json: \"{\\\"Naam\\\":\\\"UpperN\\\", \\\"Id\\\":5, \\\"Test_field\\\":\\\"lowerSnake\\\"}\", keyPath: nil, codingStrategy: customCodingStragegy) else {\n      print(\"Could not custom case convert\")\n      return\n   }\n   print(\"read object with custom key coding from json to \\(String(describing:    \n}\n\nstruct TestCodable : Codable {\n   var naam: String?\n   var id: Int?\n    var testField: String?    \n}\n```\n\nbesides the keyPath a shown in the sample code above you could also add one or more of the folowing parameters which are part of the standard JSONDecoder. If these parameters are not supplied, then the default value (see what's after the =) will be used.\n\n```\nkeyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .convertFromSnakeCase,\ndateDecodingStrategy: JSONDecoder.DateDecodingStrategy = .deferredToDate,\ndataDecodingStrategy: JSONDecoder.DataDecodingStrategy = .base64,\nnonConformingFloatDecodingStrategy: JSONDecoder.NonConformingFloatDecodingStrategy = .throw\n```\n\n## License\n\nStuff is available under the MIT 3 license. See the LICENSE file for more info.\n\n## My other libraries:\nAlso see my other public source iOS libraries:\n\n- [EVReflection](https://github.com/evermeer/EVReflection) - Reflection based (Dictionary, CKRecord, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift \n- [EVCloudKitDao](https://github.com/evermeer/EVCloudKitDao) - Simplified access to Apple's CloudKit\n- [EVFaceTracker](https://github.com/evermeer/EVFaceTracker) - Calculate the distance and angle of your device with regards to your face in order to simulate a 3D effect\n- [EVURLCache](https://github.com/evermeer/EVURLCache) - a NSURLCache subclass for handling all web requests that use NSURLReques\n- [AlamofireOauth2](https://github.com/evermeer/AlamofireOauth2) - A swift implementation of OAuth2 using Alamofire\n- [EVWordPressAPI](https://github.com/evermeer/EVWordPressAPI) - Swift Implementation of the WordPress (Jetpack) API using AlamofireOauth2, EVReflection and Alamofire (work in progress)\n- [PassportScanner](https://github.com/evermeer/PassportScanner) - Scan the MRZ code of a passport and extract the firstname, lastname, passport number, nationality, date of birth, expiration date and personal numer.\n- [AttributedTextView](https://github.com/evermeer/AttributedTextView) - Easiest way to create an attributed UITextView with support for multiple links (url, hashtags, mentions).\n- [UITestHelper](https://github.com/evermeer/UITestHelper) - UI test helper functions.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevermeer%2Fstuff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevermeer%2Fstuff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevermeer%2Fstuff/lists"}