Bundle.main.path(forResource:ofType:inDirectory:) returns nil

尽量不要哭笑不得,我才刚回到编程行业20年。

I've spent more than 4 hours looking at references and trying code snippets to get Bundle.main.path to open my text file so I can read in data for my app (my next step is to appropriately parse it).

if let filepath = Bundle.main.path(forResource: "newTest", ofType: "txt")
{
do
{
let contents = try String(contentsOfFile: filepath)
print(contents)


}
catch
{
print("Contents could not be loaded.")
}
}
else
{
print("newTest.txt not found.")
}

结果是: “ newTest.txt not found。”无论我如何尝试将文件拖放到项目中,在 Xcode 中创建文件或使用 File-> Add Files to... 菜单项。

95556 次浏览

我认为你不需要 inDirectory:方法,试试这个:

if let filepath = Bundle.main.path(forResource: "newTest", ofType: "txt") {

Swift 3.0

let fileNmae = "demo"
        

let path = Bundle.main.path(forResource: fileName, ofType: "txt")
do {
let content = try String(contentsOfFile:path!, encoding: String.Encoding.utf8)
print(content)
} catch {
print("nil")
}

SWIFT 2.0

do{
if let path = NSBundle.mainBundle().pathForResource("YOURTXTFILENAME", ofType: "txt"){
let data = try String(contentsOfFile:path, encoding: NSUTF8StringEncoding)
let myStrings = data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
print(myStrings)
}
} catch let err as NSError {
//do sth with Error
print(err)
}

Output :

Hello Hems
Good Morning
I m here for you dude.
Happy Coding.

在添加文件时,双击 add files菜单中的 Options。必须勾选 Add to targets中的目标才能将其添加到包中:

In case you are actually in another bundle (test for instance), use:

guard let fileURL = Bundle(for: type(of: self)).url(forResource: fileName withExtension:"txt") else {
fatalError("File not found")
}

问题是这个文件没有被复制到你的应用程序包中:

  • 点击你的项目
  • 瞄准目标
  • 选择构建阶段
  • 展开复制包资源
  • 单击“ +”并选择您的文件。

啊,所以我发现自己正在处理和 OP 一模一样的问题。

问题是,当代码在操场上执行时,给出的 给你给你解决方案不起作用,因为 add filesOptions菜单看起来不同,因为它没有显示 Add to targets字段:

enter image description here

When inside a .playground file, instead press the Hide or show the Navigator button on the top-right of your Xcode window (visual impression)--> enter image description here

然后,一旦 Navigator 在 Xcode 窗口的左侧打开,只需将文件拖放到操场的 Resources目录即可。

如果你的设置看起来像下面这样,你应该没问题:

enter image description here

同样的问题,略有不同的情况和解决方案。我遵循的教程说,使用以下代码:

    // Start the background music:
if let musicPath = Bundle.main.path(forResource:
"Sound/BackgroundMusic.m4a", ofType: nil) {
print("SHOULD HEAR MUSIC NOW")
let url = URL(fileURLWithPath: musicPath)


do {
musicPlayer = try AVAudioPlayer(contentsOf: url)
musicPlayer.numberOfLoops = -1
musicPlayer.prepareToPlay()
musicPlayer.play()
}
catch { print("Couldn't load music file") }
}
}

我和其他人有同样的问题,但没有一个解决方案能解决这个问题。在实验之后,我所做的就是在下面的调用中将 声音从路径中移除,一切都工作正常:

Bundle.main.path(forResource: "BackgroundMusic.m4a", ofType: nil)

It would seem that the tutorial was in error by telling me to include 声音 in the path.

我添加了 file.txt到我的项目,它是自动添加到我的项目的 Copy Bundle Files。对我来说,我不得不从 forResource中移除扩展,它起作用了。

let path = Bundle.main.path(forResource: "file", ofType: "txt") // not forResource: "file.txt"

单击导航面板上的文件,打开右侧面板/属性检查器。

enter image description here

确保添加到目标成员

这对我很有帮助: Xcode-将文件夹结构复制到我的应用程序包中

在嵌套文件夹中创建资产时,请标记“创建文件夹引用”选项。

然后像下面这样找到文件的路径:

let path = Bundle(for: type(of : self)).path(forResource: "some_folder_a/some_folder_b/response.json", ofType: nil)

这么简单的问题要花费多少时间,真是不可思议。

这里的一些答案对我有所帮助,但我一直在尝试:

Bundle.main.url(forResource: selectedTitle, withExtension: "mp3")

由于某些原因,这种方法不起作用,但是获取路径并将其转换为 URL 之后就可以了:

let path = Bundle.main.path(forResource: selectedTitle, ofType: "mp3")
let url = URL(fileURLWithPath: path!)

我的问题在一个模块中,由 Cocoapods 创建。每次 pod 安装/更新时,文件(json 文件)都在项目中,但从未在 Bundle 中找到。在 pod 安装/更新之后,我删除(删除引用)文件并再次添加到项目中。

Always pay attention to target where you add the files.

答案很简单,不要使用 Assets.xcassets 来存储音频文件, 并添加您的音频文件,即) BeTheFirstAudio.m4a (使用 QuickTime 制作) ,直接到 PROJECT NAVIGator (圆圈,粉红色)文件列表(图1)

enter image description here

警告!当从 Finder 窗口拖动音频文件出现弹出窗口时,一定要选中“ CREATEGROUPS”和“ ADD TO TARGETS”复选框。

enter image description here

After that, your code should work to play the audio (including .m4a extensions from QuickTime)

 import AVFoundation


class AudioPlayer: NSObject {




private var audioPlayer: AVAudioPlayer!


override init() {
super.init()
    

// get URL for the default audio
let audioURL = Bundle.main.url(forResource: "BeTheFirstAudio", withExtension: "m4a")


audioPlayer = try! AVAudioPlayer(contentsOf: audioURL!)
}

苹果的工程师们应该感到羞愧,这个问题甚至在 StackOverflow 中也是一个问题; 开发人员应该能够将音频文件添加到 Assets.xcassets 中,Bundle.main.url 应该能够找到它。事实上,这个简单的概念是困难的,可能已经花费了开发人员很多时间。注意@苹果

如果你正在使用 R ・斯威夫特,试试这个:

我仍然有问题,特别是与 plist 文件被更改在构建时,因为我的项目是使用 R。迅捷,我改变了代码

Bundle.main.path(forResource: R.file.myplistfile)

and that worked like a charm.

值得一提

如果您正在运行单元测试或 ui 测试,请使用它们的 bundle id。因为它们没有使用 main bundle,所以您永远不会通过调用 Bundle.main.path(forResource: "newTest", ofType: "txt")来找到您的文件。

使用您的测试目标包 id。在我的例子中,我试图从 CSV 文件中读取数据。用扩展自 XCTestCase的类名替换 TestReadFileUITests

下面是我运行 UI 测试用例时实际使用的 bundle id。你可以看到它不是来自 main bundle。

(lldb) po testBundle
NSBundle </Users/zhouhaibo/Library/Developer/CoreSimulator/Devices/448D1FCB-8311-4D3F-BEEF-934052C3470F/data/Containers/Bundle/Application/905C2326-8313-410F-9DC2-9D84B9C6D757/TestReadFileUITests-Runner.app/PlugIns/TestReadFileUITests.xctest> (loaded)


(lldb) po filePath
"/Users/zhouhaibo/Library/Developer/CoreSimulator/Devices/448D1FCB-8311-4D3F-BEEF-934052C3470F/data/Containers/Bundle/Application/905C2326-8313-410F-9DC2-9D84B9C6D757/TestReadFileUITests-Runner.app/PlugIns/TestReadFileUITests.xctest/Patients_2022-09-02.csv"
let testBundle = Bundle(for: TestReadFileUITests.self)
guard let filePath = testBundle.path(forResource: fileName, ofType: fileType) else {
print("CSV file not found.")
return [:]
}
class TestReadFileUITests: XCTestCase {


func testDemo() {
let _ = DataManager.readData()
}
}

通过将文件从 资产目录移动到常规文件夹,我解决了一个类似的问题。

我本来打算投零分的

let myPath = Bundle.main.path(forResource: "Terms", ofType: "json")

I had named my file "Terms.JSON" When I realized it should be "Terms.json". that fixed the issue.