Parzh from Ukraine
Parzh from Ukraine

Reputation: 9863

Could not find a *.json file inside an Xcode 12 project

I'm trying both Swift (5.3) and Xcode (12) for the first time. The task is to parse a *.json file, that already exists nearby.

Honestly, adding the file in Xcode project is more tricky than actually parsing it: wherever I put it, it is always not found. This answer didn't help, because there's no Target Membership section in File Inspector (I guess, it was renamed or moved somewhere else in Xcode 12; maybe I'm wrong; anyway, couldn't find it as well).

I've also noticed that there's a difference in behavior of Target Membership section, when creating a new Project versus new Swift Package. If it is a Project, then Target Membership shows up. Since I've created a package, this section is not available for me.

Could someone help me understand what's going on here?


I don't know how this works, I don't know what exactly I'm supposed to do to "add a new member in the target", I don't know what targets and products are, and I'm frustrated that adding files in Xcode requires that much of an effort.

Upvotes: 1

Views: 1809

Answers (1)

JeremyP
JeremyP

Reputation: 86651

With Swift 5.3, packages have the ability to add and process non code resources. However, the Package.swift has to explicitly define them. Do this by adding the resources to the target:

targets: [
  .target(
    name: "TryParseJSON",
    resources: [
      .copy("persons.json")
    ]
  )
]

That will copy it into the Bundle, hopefully in the right place. If not, there may be extra config required.

Note that the path is relative to the directory containing the sources for the target. Apple recommends creating a subdirectory inside your source directory called Resources. If you do that you need

      .copy("Resources/persons.json")

Also, make sure Package.swift defines Swift tools 5.3 at the top like this:

// swift-tools-version:5.3

It also matters how you try to extract the URL of the file when you need to access it. According to the Apple docs, you must always use Bundle.module.url(forResource:,withExtension:) to get the URL of the resource. So, in the above case use

guard let resourceUrl = Bundle.module.url(forResource: "persons",withExtension: "json")
else { /* fail */ }

Upvotes: 1

Related Questions