Objective-C 从 .plist 中检索的样式在 Swift 中不起作用?

Objective-C style retrieving from .plist not working in Swift?

每当我的视图通过以下方法加载时,我都在 Objective-C 中的 .plist 中检索数据 -

@interface ListTableViewController ()

@end

@implementation ListTableViewController
NSArray *dict;

-(void)viewDidAppear:(BOOL)animated
{
    NSString *arr= [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

    arr=[arr stringByAppendingPathComponent:@"datalist.plist"];
    if ([[NSFileManager defaultManager]fileExistsAtPath:arr])
    {
       dict=[NSArray arrayWithContentsOfFile:arr];
        NSLog(@"%@",dict);

    }
    [self.tableView reloadData];

}

现在 Swift 我正在做与 -

相同的事情
class ListTableViewController: UITableViewController{
  var arr = NSArray()
  var plistfinalpath = String()

  override func viewDidAppear(animated: Bool){
      let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, .UserDomainMask, true)[0]
      plistfinalpath = path.stringByAppendingString("/login.plist")
      print(plistfinalpath)
      print("time of appearing\(arr)")

      arr = NSArray(contentsOfFile: plistfinalpath)!
      self.tableView.reloadData()
  }
}

但是因为当应用程序第一次启动时 plist 为空时我必须解包行 arr = NSArray(contentsOfFile: plistfinalpath)! 中的值,所以数组为空并且因为我正在解包它,它显示错误.那么我怎样才能实现我在 objective C 中所做的事情呢?

只需将 arr 变量定义为可选变量,如下所示:
var arr:NSArray? = NSArray()

当一个变量被定义为非可选时,你不能使它成为nil。您使用的 NSArray 初始值设定项被定义为 public convenience init?(contentsOfFile path: String) - ? 意味着,它实际上可以 return a nil。当您使用 ! 时,您强制解包该值,当值为 nil.

时会导致运行时崩溃

与往常一样,您可以在 docs

中阅读更多内容

或者,您可以这样做:

if let tempArr = NSArray(contentsOfFile: plistfinalpath) {
    arr = tempArr
}

这样,您不需要将 arr 定义为可选的,并且只会在文件内容不为空时分配给它。

完整的答案涉及理解 "optional" 的概念。

什么是可选的?

在 Swift 中,您可以在类型后附加 ? 将变量声明为可选。当您这样做时,这意味着该变量可以保存一个值或根本不保存。当您将变量声明为非可选变量时,编译器会确保它始终保存一个值。

  • 声明一个变量为可选:var myOptionalVariable: NSArray?
  • 将变量声明为非可选变量:var myVariable = NSArray()

注意在非可选变量中,编译器强制我们给它一个值(在本例中只是一个空数组)。这是因为编译器允许当一个变量不是可选的时,它在每时每刻都有一个值。 注意区别:第一个语句只是声明变量作为可选NSArray,第二个语句初始化并分配一个新的空NSArray给变量。

为什么可选的有用?

随着可选值的引入,我们对变量中包含的数据的存在有了编译时安全性。当不使用可选变量时,我们肯定知道变量始终保持一个值。同时,当使用可选变量时,我们不得不处理值可能不存在的情况,而不是默默地处理它(这就是 [=79= 中的 nil 发生的情况]).从可选中提取值称为 unwrapping

解包可选(即从可选中提取值)

要"extract" 可选变量的值,您需要将其解包。有几种方法可以解包一个可选变量,假设 myOptional 是一个可选变量,这里有一些例子:

if let variable = myOptional { 
    // I can safely use variable here
}

甚至这个其他语法:

variable = myOptional ?? defaultNonOptionalValue
// I can safely use variable here

此外,您可以使用

进行强制解包
variable = myOptional!
// crash incoming?

您使用这种方式进行解包,但实际上您是在对编译器说“相信我,我知道 myOptional 永远不会为 nil”这在你的情况下是不正确的,它会导致崩溃并出现错误 Fatal error: unexpectedly found nil while unwrapping an Optional values。您应该始终避免强制解包,除非您真的非常确定您的数据。

长话短说

您有 2 个可行的解决方案:

  • 不要使用强制解包(参见上面关于解包的选项)
  • 将您的变量 arr 转换为可选变量(通过以这种方式声明它:var arr: NSArray?),然后在您使用它时处理(非强制)展开(即在您的 tableView 中)数据源方法)

哪一个更适合你的情况,取决于 arr 的意思,如果它是可选的有意义,那就去做吧,否则,就让它不可选并分配一些默认值。

只需使用以下代码,

if let array = NSArray(contentsOfFile: plistfinalpath){
   arr = array
}

在swift中,(!)用于强制解包可选值。 当可选值有值时,你应该使用它,否则你应该使用上面的代码。