Strong typed, autocompleted resources like images, fonts and segues in Swift projects

Overview

R.swift Version License Platform

Get strong typed, autocompleted resources like images, fonts and segues in Swift projects

Why use this?

It makes your code that uses resources:

  • Fully typed, less casting and guessing what a method will return
  • Compile time checked, no more incorrect strings that make your app crash at runtime
  • Autocompleted, never have to guess that image name again

Currently you type:

let icon = UIImage(named: "settings-icon")
let font = UIFont(name: "San Francisco", size: 42)
let color = UIColor(named: "indicator highlight")
let viewController = CustomViewController(nibName: "CustomView", bundle: nil)
let string = String(format: NSLocalizedString("welcome.withName", comment: ""), locale: NSLocale.current, "Arthur Dent")

With R.swift it becomes:

let icon = R.image.settingsIcon()
let font = R.font.sanFrancisco(size: 42)
let color = R.color.indicatorHighlight()
let viewController = CustomViewController(nib: R.nib.customView)
let string = R.string.localizable.welcomeWithName("Arthur Dent")

Check out more examples or hear about how Fabric.app uses R.swift!

Demo

Autocompleted images:

Autocompleted images

Compiletime checked images:

Compiletime checked images

This is only the beginning, check out more examples!

CocoaHeadsNL presentation

Mathijs Kadijk presented R.swift at the September 2016 CocoaHeadsNL meetup. Talking about the ideas behind R.swift and demonstrating how to move from plain stringly-typed iOS code to statically typed code.

R.swift presentation at CocoaHeadsNL

Features

After installing R.swift into your project you can use the R-struct to access resources. If the struct is outdated just build and R.swift will correct any missing/changed/added resources.

R.swift currently supports these types of resources:

Runtime validation with R.validate():

  • If all images used in storyboards and nibs are available
  • If all named colors used in storyboards and nibs are available
  • If all view controllers with storyboard identifiers can be loaded
  • If all custom fonts can be loaded

Q&A

Installation

CocoaPods is the recommended way of installation, as this avoids including any binary files into your project.

Note on Carthage: R.swift is a tool used in a build step, it is not a dynamic library. Therefore it is not possible to install it with Carthage.

CocoaPods (recommended)

  1. Add pod 'R.swift' to your Podfile and run pod install
  2. In Xcode: Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab and add a New Run Script Phase by clicking the little plus icon in the top left
  3. Drag the new Run Script phase above the Compile Sources phase and below Check Pods Manifest.lock, expand it and paste the following script:
    "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/R.generated.swift"
    
  4. Add $TEMP_DIR/rswift-lastrun to the "Input Files" and $SRCROOT/R.generated.swift to the "Output Files" of the Build Phase
  5. Build your project, in Finder you will now see a R.generated.swift in the $SRCROOT-folder, drag the R.generated.swift files into your project and uncheck Copy items if needed

Screenshot of the Build Phase can be found here

Tip: Add the *.generated.swift pattern to your .gitignore file to prevent unnecessary conflicts.

Mint

First, Install R.Swift Binary and Run Script Phase

  1. Add mac-cain13/R.swift to your Mintfile and run mint bootstrap to install this package without linking it globally (recommended)
  2. In Xcode: Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab and add a New Run Script Phase by clicking the little plus icon in the top left
  3. Drag the new Run Script phase above the Compile Sources phase, expand it and paste the following script:
    if mint list | grep -q 'R.swift'; then
      mint run R.swift rswift generate "$SRCROOT/R.generated.swift"
    else
      echo "error: R.swift not installed; run 'mint bootstrap' to install"
      return -1
    fi
    
  4. Add $TEMP_DIR/rswift-lastrun to the "Input Files" and $SRCROOT/R.generated.swift to the "Output Files" of the Build Phase
  5. Build your project, in Finder you will now see a R.generated.swift in the $SRCROOT-folder, drag the R.generated.swift files into your project and uncheck Copy items if needed

Tip: Add the *.generated.swift pattern to your .gitignore file to prevent unnecessary conflicts.

Second, Install R.Swift.Library via the Swift Package Manager (requires Xcode 11)

If you see a build error No such module 'Rswift' when trying to #import Rswift at the top of the R.generated.swift file, then you will also need to install the library via the Swift Package Manager available in Xcode 11+.

Head over to the R.Swift.Library repo and follow the Swift Package Manager installation instructions.

Homebrew

R.swift is also available through Homebrew. This makes it possible to install R.swift globally on your system. Install R.swift by running: brew install rswift. The Homebrew formula is maintained by @tomasharkema.

Manually

  1. Add the R.swift.Library to your project
  2. Download a R.swift release, unzip it and put it into your source root directory
  3. In Xcode: Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab and add a New Run Script Phase by clicking the little plus icon in the top left
  4. Drag the new Run Script phase above the Compile Sources phase, expand it and paste the following script:
    "$SRCROOT/rswift" generate "$SRCROOT/R.generated.swift"
    
  5. Add $TEMP_DIR/rswift-lastrun to the "Input Files" and $SRCROOT/R.generated.swift to the "Output Files" of the Build Phase
  6. Build your project, in Finder you will now see a R.generated.swift in the $SRCROOT-folder, drag the R.generated.swift files into your project and uncheck Copy items if needed

Screenshot of the Build Phase can be found here

Tip: Add the *.generated.swift pattern to your .gitignore file to prevent unnecessary conflicts.

Building from source

R.swift is built using Swift Package Manager (SPM).

  1. Check out the code
  2. Run swift build -c release from the root directory
  3. Follow the manual installation steps with the binary you now have

For developing on R.swift in Xcode, run swift package generate-xcodeproj --xcconfig-overrides RswiftConfig.xcconfig.

Contribute

We'll love contributions, read the contribute docs for info on how to report issues, submit ideas and submit pull requests!

License

R.swift and R.swift.Library are created by Mathijs Kadijk and released under a MIT License.

Special thanks to Tom Lokhorst for his major contributions and help maintaining this project.

Comments
  • Cannot archive project in Xcode 13 - input file 'R.generated.swift' was modified during the build

    Cannot archive project in Xcode 13 - input file 'R.generated.swift' was modified during the build

    Greetings! A project that worked perfectly fine in Xcode 12.5.1 and earlier doesn't archive anymore in Xcode 13 Beta 5. It fails with this error.

    CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler (in target 'Vectornator' from project 'Vectornator')
    <Build command>
    error: input file '/PrivatePath/Other Sources/R.generated.swift' was modified during the build
    error: input file '/PrivatePath/Other Sources/R.generated.swift' was modified during the build
    Command CompileSwiftSources failed with a nonzero exit code
    

    The project is an iOS app with a Catalyst version. iOS builds, runs and archives fine. Catalyst builds and runs fine, but fails to archive. Here's the build phase setup. Bildschirmfoto 2021-09-13 um 18 18 31

    Does anyone have any idea what's going wrong? Bildschirmfoto 2021-09-13 um 18 15 40

    I will retest with Xcode 13 RC tomorrow and update the issue.

    opened by kaiengelhardt 35
  • ⚠️ R.swift and Xcode 10 / Swift 4.2

    ⚠️ R.swift and Xcode 10 / Swift 4.2

    The currently latest alpha release of R.swift (5.0.0.alpha.2) supports Swift 4.2 and Xcode 10.

    However, there is a known build system issue. We want to fix this issue before releasing the official 5.0 version of R.swift.

    If you can work around the build system issue, feel free to use the alpha version of 5.0, it works pretty much like R.swift 4.0, but for Swift 4.2. (See complete list of differences)

    Issue: R.swift build step and the New Build System

    When the new build system is used, with a standard R.swift build step, this build step is not run before the Compile Sources build step.

    Because of this, the initial compilation will fail, because there's no R.generated.swift file, and references to the R struct in the rest of the source code are invalid.

    While it's easy to "build twice" during development in Xcode, this is particularly a problem on CI servers, where the build will simply fail because of the missing R.generated.swift file.

    Partial solution: Adding R.generated.swift as an output file

    As a fix for the above issue, you can add R.generated.swift as an output file:

    This will make sure the R.swift step has finished, before the Compile Sources step starts. However, with this output file, the step will only run once:

    Issue: Build step with output file only runs once

    When R.generated.swift is configured as the output file (and there are no input files), the R.swift build step will only run once. On subsequent incremental builds, the step is skipped. Because of this, new resources won't show up in the R struct.

    It is sometimes possible to list the resource files used als input files for the build step, but not always.

    For example, when adding a new image to the asset catalog, the new filename isn't known beforehand.

    Workarounds

    These are possible workarounds:

    1. Use the Legacy Build System. This behaves like before, and the R.swift build step will always run.
    2. Commit the R.generated.swift file. This means during development, you can "build twice" and commit the resulting up-to-date file to git.
    3. Clean build when resources change. Configure the output file for the build step, and manually do a clean build whenever one of the resources are changed.

    None of these workarounds are ideal, so we're still looking for a proper solution.

    opened by tomlokhorst 30
  • Support skipping files

    Support skipping files

    This is a first draft of skipping resource files.

    Not Implemented, yet

    At this moment, following features are not implemented.

    • wildcard
    • skipping all files in folder
    • must not start with "/" (.gitignore ignores first slashes)
    • negation ("!" symbol at the beginning of the line)

    Sample skip file

    Same as .gitignore file, developers should specify relative path from --rswiftignore file. (I don't think it should accept using "..")

    # filter Colors.jpg
    ResourceApp/Images/Colors.jpg
    # filter GdyBkltter1911.ttf
    ResourceApp/Fonts/GdyBkltter1911.ttf
    

    Other comments

    I cherry-pick your commits but some of them conflict with master. So, you better check all of the commits listed here.

    Let me know if you want me to squash my commits.

    Thanks, in advance!

    opened by shiraji 26
  • R.swift not generated

    R.swift not generated

    Hi I have problem in using R.swift. I do every step of installing R.swift using Pods in Xcode 10 but I have this error and no R.generated.swift generated : [R.swift] The folder “R.generated.swift” doesn’t exist.

    opened by erfanwakka 20
  • Add support for loading local project files

    Add support for loading local project files

    Can we add support to recognize the local files stored in the project? Sometimes we add videos, html or json files to the project directory. We should add capability to recognize those files as assets as well.

    Happy to create a PR for this if someone can give me directions on how to implement.

    opened by RishabhTayal 19
  • Info plist is not resolved using environment variables, this is causing errors

    Info plist is not resolved using environment variables, this is causing errors

    I installed with CocoaPods.

    Then i got warning [R.swift] File could not be parsed as Info Plist from URL: /path/to/project/module_name/ $(SRCROOT)/project_name/my_path/Info.plist on xcode 11.2.1.

    However i can use R.swift methods.

    Using version

    • Xcode 11.2.1
    • CocoaPods: 1.8.4
    • R.swift (5.1.0)
    • R.swift.Library (5.1.0)

    BuildPhase

    opened by kumanmushi 18
  • R.swift Cocoapods Run Script Illegal instruction

    R.swift Cocoapods Run Script Illegal instruction

    Hello,

    We are trying to get R.swift setup with our project and we are running into the following error when building the project.

    Command /bin/sh failed with exit code 132

    We installed R.swift via Cocoapods and added the following Run Script above Compile Sources and below Check Pods Manifest.

    "$PODS_ROOT/R.swift/rswift" "$SRCROOT"

    We were able to get R.swift to work in a newly created project.

    We are using Xcode 8.3.3 and targeting iOS 9.0. The project is Objective-C and Swift 3.

    Any help would be greatly appreciated! :)

    opened by pjvea 18
  • Use of undeclared type 'GRKStoryboardProxyViewController'

    Use of undeclared type 'GRKStoryboardProxyViewController'

    I am using R.swift in my project. I some of my view controllers are of instances of GRKStoryboardProxyViewController.

    I have upgraded to R.swift version 3.1.0 and now the R.generated.swift file doesn't import GRKStoryboardProxyViewController

    I am getting "use of undeclared type" errors in

    /// Optionally returns a typed version of segue `showCustomer`.
    /// Returns nil if either the segue identifier, the source, destination, or segue types don't match.
    /// For use inside `prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)`.
    static func showCustomer(segue: UIKit.UIStoryboardSegue) -> Rswift.TypedStoryboardSegueInfo<UIKit.UIStoryboardSegue, BookingViewController, GRKStoryboardProxyViewController>? {
        return Rswift.TypedStoryboardSegueInfo(segueIdentifier: R.segue.bookingViewController.showCustomer, segue: segue)
    }
    

    and other parts of the file where GRKStoryboardProxyViewController is referenced

    I am sorry in I have done some thing wrong and this is not an issue, but any help would be greatly appreciated

    type: issue 
    opened by markGilchristBookingBug 18
  • First build always fails using the new build system with Xcode 10 Beta 6

    First build always fails using the new build system with Xcode 10 Beta 6

    Hi,

    Using the new build system (the default setting) with Xcode 10 Beta 6 results in the first build failing. Subsequent builds pass.

    Configuration

    • Xcode 10 Beta 6
    • R.swift added via cocoapods
    • R.swift build script as follows $PODS_ROOT/R.swift/rswift" "generate" "$SRCROOT

    Result error: Build input file cannot be found: '/Project/R.generated.swift'

    On a local machine, this is not a problem, as we can build again. However, on a CI environment such as Buddybuild, the build continuously fails as it performs a clean build every time.

    opened by superpeteblaze 17
  • Localised Strings in addition to currentLocale

    Localised Strings in addition to currentLocale

    I would like to use localized strings in addition to NSLocale.currentLocale().

    Pattern 1:

    struct string {
      struct localizable {
        let locale: NSLocale
        init(locale: NSLocale = NSLocale.currentLocale()) {
          self.locale = locale
        }
        /// Locales: en, ja
        static func helloWorld() -> String {
            return String(format: NSLocalizedString("HelloWorld", comment: ""), locale: self.locale)
        }
      }
    }
    

    Pattern 2:

    struct string {
      struct en {
        /// Locales: en, ja
        static func helloWorld() -> String {
            return String(format: NSLocalizedString("HelloWorld", comment: ""), locale: NSLocale(localeIdentifier: "en"))
        }
      }
    }
    
    type: enhancement 
    opened by uny 17
  • R.generated.swift is not re-generated without a clean build on 5.0.0 final

    R.generated.swift is not re-generated without a clean build on 5.0.0 final

    Hi!

    I was using R.swift 5.0.0-alpha2 and had a unit test running validate() which was correctly failing whenever I had a wrong asset or font in a XIB:

    XCTAssertNoThrow(try R.validate())
    

    I've just updated to 5.0.0 and checked if that was still working before merging this update, but the test now passes for the same incorrect asset/font that fails the test at 5.0.0-alpha2.

    Am I doing this in a deprecated way or is the feature broken?

    Thanks!

    opened by gobetti 15
  • .rswiftignore doesn't work for one of the folders inside assets

    .rswiftignore doesn't work for one of the folders inside assets

    In my project, there is a folder with images that should be used only for working with the database, and in my code I do not explicitly refer to them (for example, R.image.closeIcon()). This directory is located inside asset and has the path: /Users/anatoliy/Documents/develop/work/ELEL/iOS/mobile-ios23/DMVGenius/Resources/Assets/AssetsDMV.xcassets/imagesUS

    I attached a screenshot of what the asset structure looks like in Xcode and in Finder:

    I added exceptions to the .rswiftignore file for such a folder so that R.swift objects are not generated for the image from this folder:

    # **/AssetsDMV.xcassets/imagesUS/*
    
    DMVGenius/Resources/Assets/AssetsDMV.xcassets/imagesUS
    
    **/imagesUS/*
    

    But that didn't work for me and I still get xcode warnings:

    [R.swift] Skipping 974 images because no swift identifier can be generated for all of these images: '050520132206252694', '050520132211282376', '110320131739549584', '110320131744509927', '140320131714351981', '1573301280', 
    ...
    '202007151952104222', '202007152024341579', '202007161124338470', '202007161144073258', '202007161144073258', '202007161153196086', '202007161212064082', '202007161212064082', '202007161221019734', '202007161221019734', '202007170350016908', '202007170527116755', '202007170532436592', '202007170536349573', '202007170635053253', '202007170650315090', '202007170657369869', '202007170703183192', '202007170745173728', '202007170818264860', '202007170851405575', '202007170859214677', '202007170905174666', '202007170913136452', '202007170920546009', '202007170927083469', '202007171714203189', '202007171751013120', 'LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted
    

    Any ideas how to get the exception to work and not throw errors for a particular directory (imagesUS)?

    P.S. The remaining folders with images and icons inside this assets are used by me explicitly in the project code.

    type: issue 
    opened by anatoliykant 1
  • R.swift can't populate the R.generated.swift file of a pod imported via CocoaPods

    R.swift can't populate the R.generated.swift file of a pod imported via CocoaPods

    This is what I wrote in the pod spec file:

    s.dependency 'R.swift'

    s.script_phases = [{ :name => 'R', :script => '"$PODS_ROOT/R.swift/rswift" generate --access-level public "$SRCROOT/FolderName/R.generated.swift"', :execution_position => :before_compile, :input_files => ["$TEMP_DIR/rswift-lastrun"], :output_files => ["$SRCROOT/FolderName/R.generated.swift"] }]

    And this is what the R.generated.swift file produces:

    private class BundleFinder {} let R = _R(bundle: Bundle(for: BundleFinder.self))

    struct _R { let bundle: Foundation.Bundle func validate() throws {

    }

    struct project { let developmentRegion = "en" } }

    The R.swift version is : 7.1.0

    opened by AntonioEmanueleCutarella98 0
  • Issue with Xcode Cloud

    Issue with Xcode Cloud

    Hi there,

    We recently migrated to V7, and it works perfectly, in our local machine and CircleCI.

    The issue now is with Xcode Cloud, as we are getting this error from logs.

    PhaseScriptExecution R.swift\ generate\ resources\ for\ application\ APPLICATION_NAME/Volumes/workspace/DerivedData/Build/Intermediates.noindex/APPLICATION_NAME.build/Debug-iphonesimulator/APPLICATION_NAME.build/Script-72183A77293DDBE600A947EF.sh (in target 'APPLICATION_NAME' from project 'APPLICATION_NAME')
        cd /Volumes/workspace/repository
        /bin/sh -c /Volumes/workspace/DerivedData/Build/Intermediates.noindex/APPLICATION_NAME.build/Debug-iphonesimulator/APPLICATION_NAME.build/Script-72183A77293DDBE600A947EF.sh
    
    Error: You don’t have permission to save the file “R.generated.swift” in the folder "Resources".
    LLVM Profile Error: Failed to write file "default.profraw": Operation not permitted
    Command PhaseScriptExecution failed with a nonzero exit code
    

    Looks like the build script doesn't have access to Resources folder in Xcode cloud 🤔 We've done everything as the migration guideline suggested.

    Do you have any suggestion? 🤔

    Thanks!

    type: issue 
    opened by le-tyang 9
  • Invalid redeclaration of 'bundle' on v7.x

    Invalid redeclaration of 'bundle' on v7.x

    Due to some constraints on our CICD, we need a folder reference inside the xCode project with name bundle. R.swift generates a bundle reference as a file which conflicts with the actual bundle

      /// This `_R.file` struct is generated, and contains static references to 32 resource files.
      struct file {
        let bundle: Foundation.Bundle
     
     ....
         /// Resource file `bundle`.
        var bundle: RswiftResources.FileResource { .init(name: "bundle", pathExtension: "", bundle: bundle, locale: LocaleReference.none) }
      }
    

    bundle is actually a non empty folder. Shouldn't even be generated as a file. My current solution is to just skip file generation: "$PODS_ROOT/R.swift/rswift" generate --generators image,string,color,font "$SRCROOT/R.generated.swift"

    Screenshot 2022-11-30 at 18 05 13 type: issue 
    opened by ilkerc 1
Releases(7.2.4)
Owner
Mathijs Kadijk
CTO @getmibo — We're hiring ✨
Mathijs Kadijk
GenStore is a lightweight swift code generator for your resources.

GenStore is a lightweight swift code generator for your resources. GenStore can create classes for your images, colors and localized strings.

null 11 Oct 23, 2021
ALO sync allows you to sync resources form an ALO endpoint to your macOS file system.

ALO sync allows you to sync resources form an ALO endpoint to your macOS file system. Prerequisites macOS 11 No support for search* No suppor

Lawrence Bensaid 2 Jan 22, 2022
A result builder that build HTML parser and transform HTML elements to strongly-typed result, inspired by RegexBuilder.

HTMLParserBuilder A result builder that build HTML parser and transform HTML elements to strongly-typed result, inspired by RegexBuilder. Note: Captur

null 4 Aug 25, 2022
🏹 Bow is a cross-platform library for Typed Functional Programming in Swift

Bow is a cross-platform library for Typed Functional Programming in Swift. Documentation All documentation and API reference is published in our websi

Bow 613 Dec 20, 2022
Useful Swift code samples, extensions, functionalities and scripts to cherry-pick and use in your projects

SwiftyPick ?? ?? Useful Swift code samples, extensions, functionalities and scripts to cherry-pick and use in your projects. Purpose The idea behind t

Manu Herrera 19 May 12, 2022
SharkUtils is a collection of Swift extensions, handy methods and syntactical sugar that we use within our iOS projects at Gymshark.

SharkUtils is a collection of Swift extensions, handy methods and syntactical sugar that we use within our iOS projects at Gymshark.

Gymshark 1 Jul 6, 2021
A collection of common tools and commands used throughout the development process, customized for Kipple projects.

KippleTools A collection of common tools and commands used throughout the development process, customized for Kipple projects. ⚠️ The code in this lib

Kipple 10 Sep 2, 2022
A Swift port of some of the original PersistentJXA projects by D00MFist

Persistent-Swift This repo is a Swift port of some of the original PersistentJXA projects by D00MFist (https://github.com/D00MFist/PersistentJXA). I p

Cedric Owens 25 Sep 27, 2022
FeatureFlags.swift - Tools for easily defining feature flags for your projects

FeatureFlags.swift Tools for easily defining feature flags for your projects Int

Eric Rabil 1 Jan 31, 2022
A documentation generator for Swift projects

swift-doc A package for generating documentation for Swift projects. Given a directory of Swift files, swift-doc generates HTML or CommonMark (Markdow

SwiftDoc 1.7k Dec 6, 2022
This is a app developed in Swift, using Object Oriented Programing, UIKit user interface programmatically, API Request and Kingfisher to load remote images

iOS NOW ⭐ This is a app developed in Swift, using Object Oriented Programing, UIKit user interface programmatically, API Request and Kingfisher to loa

William Tristão de Paula 1 Dec 7, 2021
iOS helper library that contains commonly used code in Uptech iOS projects

iOS helper library that contains commonly used code in Uptech iOS projects.

Uptech 1 Apr 1, 2022
It makes a preview from an URL, grabbing all the information such as title, relevant texts and images.

Link Previewer for iOS, macOS, watchOS and tvOS It makes a preview from an URL, grabbing all the information such as title, relevant texts and images.

Leonardo Cardoso 1.3k Jan 2, 2023
SwiftExtensionsPlayground - This playground includes some extensions that I like to use

This playground includes some extensions that I like to use. You can find exampl

Fırat Yenidünya 0 Jan 6, 2022
WholesomeExtensions - A SPM package that provides some extensions that I like to use

WholesomeExtensions This package includes some extensions that I like to use. Yo

Fırat Yenidünya 2 Dec 30, 2022
[iOS] Animated analog flip numbers like airport/train-station displays (SwiftUI)

A SwiftUI FlipNumberView A small universal (iOS + macOS) app displaying the current time with a flip animation. This is still WIP and doesn't support

M Emrich 6 Dec 6, 2022
Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer documentation.

Swift-DocC is a documentation compiler for Swift frameworks and packages aimed at making it easy to write and publish great developer docum

Apple 833 Jan 3, 2023
BCSwiftTor - Opinionated pure Swift controller for Tor, including full support for Swift 5.5 and Swift Concurrency

BCSwiftTor Opinionated pure Swift controller for Tor, including full support for

Blockchain Commons, LLC — A “not-for-profit” benefit corporation 4 Oct 6, 2022
Zip - A Swift framework for zipping and unzipping files. Simple and quick to use. Built on top of minizip.

Zip A Swift framework for zipping and unzipping files. Simple and quick to use. Built on top of minizip. Usage Import Zip at the top of the Swift file

Roy Marmelstein 2.3k Jan 3, 2023