【问题标题】:why does Bundle.main.path(forResource: fileName, ofType: "txt") always return nil?为什么 Bundle.main.path(forResource: fileName, ofType: "txt") 总是返回 nil?
【发布时间】:2017-05-29 08:50:13
【问题描述】:

我想逐行读取文本文件并使用example shown here将其显示在iOS屏幕上。

使textView.text 可选是我可以让readDataFromFile 运行的唯一方法。当我单击load 时,该函数运行但始终返回nil。我认为这意味着找不到该文件。

出于测试目的,我在 Xcode 中创建了文本文件。我还尝试将其保存在桌面以及项目文件夹中。无论哪种方式,它都可以从项目导航器中读取。我还尝试使用 TextEdit 创建文件,因为该应用程序最终需要读取在 Xcode 之外创建的文本文件。

如果有人能解释为什么永远找不到文本文件,我是否需要做其他事情才能让项目找到它,或者读取函数是否因其他原因返回 nil,我将不胜感激由于我实施它的方式。谢谢。

编辑 (2)

感谢您的反馈。作为回应,我做了四个小的代码更改,允许将文本文件内容写入 textView。更改包括:从文件名中删除文件扩展名,添加文件名数组,从readDataFromFile 返回String 而不是String?,并在代码中重写UITextView。这解决了我知道的问题。

这是修改后的代码

import UIKit

class ViewController: UIViewController {

var textView = UITextView()
var arrayOfStrings: [String]?
var fileNameWithExtension               = "textFile.txt"
let arrayOfFileNames                    = ["textFile1.txt", "textFile2.txt", "textFile3.txt", "textFile4.txt", "textFile5.txt"]

var fileName                            = String()

override func viewDidLoad() {
    super.viewDidLoad()

    //    remove comment in the next statement to test files named in ArrayOfFileNames    
    //    fileNameWithExtension               = arrayOfFileNames[4]

    fileName = fileNameWithExtension.replacingOccurrences(of: ".txt", with: "")

    createTextView()
    createButton()
}

func readDataFromFile(fileName: String) -> String {

   if let path                          = Bundle.main.path(forResource: fileName, ofType: nil) {

        print(fileName)

        do {
            let data                    = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
            arrayOfStrings              = data.components(separatedBy: .newlines)
            textView.text               = arrayOfStrings?.joined(separator: "\n")

        } catch {
            textView.text               = "file contents could not be loaded"
        }

    } else {
        print(Bundle.main.path(forResource: fileName, ofType: "txt") as Any)
        textView.text                   = "\(fileName) could not be found"
    }
    return textView.text
}

func createButton () {
    let button = UIButton();
    button.setTitle(String("Load"), for: .normal)
    button.setTitleColor(UIColor.blue, for: .normal)
    button.frame = CGRect(x: 100, y: 10, width: 200, height: 100)
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    self.view.addSubview(button)
}

func buttonAction(myButton: UIButton) {
    textView.text = readDataFromFile(fileName: fileName)
    print(textView.text as Any)
}

func createTextView () {
    textView = UITextView(frame: CGRect(x: 20.0, y: 75.0, width: 340.0, height: 400.0))
    textView.textAlignment = NSTextAlignment.left
    textView.textColor = UIColor.blue
    textView.backgroundColor = UIColor.white
    self.view.addSubview(textView)
    }
}

编辑 (1)

该文件在项目导航器中可见。我假设这意味着它在捆绑包中。

这是我的原始代码

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var textView: UITextView?

var arrayOfStrings: [String]?
var fileName                            = "textFile.txt"

override func viewDidLoad() {
    super.viewDidLoad()
    createButton()
}

func readDataFromFile(fileName: String) -> String? {

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

        do {
            let data                    = try String(contentsOfFile: path, encoding: String.Encoding.utf8)
            arrayOfStrings              = data.components(separatedBy: .newlines)
            print(arrayOfStrings as Any)

            textView?.text              = arrayOfStrings?.joined(separator: "/n")
            return textView?.text

        } catch {
            textView?.text              = "file contents could not be loaded"
            return textView?.text
        }

    } else {
        print(Bundle.main.path(forResource: fileName, ofType: "txt") as Any)
        textView?.text                  = "\(fileName) could not be found"
        return nil
    }
}

func createButton () {
    let button = UIButton();
    button.setTitle(String("Load"), for: .normal)
    button.setTitleColor(UIColor.blue, for: .normal)
    button.frame = CGRect(x: 100, y: 15, width: 200, height: 100)
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    self.view.addSubview(button)
}


func buttonAction(myButton: UIButton) {
    print("works")
    textView?.text                      = readDataFromFile(fileName: fileName)
    print(textView?.text as Any)
}

textFile.txt

Line 1
Line 2
Line 3
Line 4
Line 5

【问题讨论】:

  • fileName 应该是 textFile(没有扩展名)
  • ... 如果fileName 已经包含扩展名“.txt”,请致电Bundle.main.path(forResource: fileName, ofType: nil)
  • ...或者使用 URL 相关的 API Bundle.main.url(forResource: "textFile", withExtension:"txt") 更具描述性。
  • @vadian 是始终无处不在的路径,仅基于文件名从不包含文件类型的文件名?!
  • 它在 Xcode 中,但请确保将其复制到您在模拟器或设备上运行的包中。另外 - 您的文件没有扩展名 - 我相信您的代码正在寻找扩展名为 txt 的文件:Bundle.main.url(forResource: "textFile", withExtension:nil)

标签: ios swift uitextview


【解决方案1】:

1) 你在这行有错误:

var fileName = "textFile.txt"

应该是:

var fileName = "textFile"

2) 检查您的文件是否连接到目标:

【讨论】:

  • 没有区别
  • 检查,你是否为“textFile.txt”设置了正确的目标
  • 我相信你的意思是:是捆绑包中的“textFile.txt”。查看我的编辑
  • 文件也需要添加到目标中。在导航器中选择文件并在实用程序窗格中检查其目标成员资格。 stackoverflow.com/questions/14147640/…
  • @Rolleric,直到现在我才知道目标会员资格。谢谢。我现在明白伊戈尔在说什么了。现在已经进行了一些更改,这些更改可能已经解决了问题。查看我的最新编辑。当我检查每个文件上的目标成员资格复选框时,它被勾选了。对于在 Xcode 中编辑的文本文件,这必须自动发生。
【解决方案2】:

您应该考虑像这样添加类包所有者:

Bundle(for: ViewController.self).path(forResource: "fileName", ofType: "txt")

如果我是对的,这是从 swift 2.0 实现的。

【讨论】:

  • 你应该为此获得一枚奖牌!我有一个包含多个 xcode 项目的设置。在我的MainApp.xcodeproj 中,我指的是MyModule.xcodeproj,在MyModule 中,我指的是资产、视频文件(mp4),它也是MyModules 目标的一部分。但是在MyModule 的文件中使用代码Bundle.main 并不是指MyModule,而是指MainApp。因此,将您的解决方案与Bundle(for: FileInsideMyModulesTarget.self).path 一起使用解决了我的问题! :D
  • 这对我有用,同时使用带有子模块的多个项目。
猜你喜欢
  • 2019-06-30
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 2015-03-05
  • 2014-08-25
相关资源
最近更新 更多