Swift:生成对象的超类方法的替代品



我有以下Objective-C代码,我正在尝试转换为swift:

-(id)initWithBook:(NSString*)bookTitle author:(NSString*)author description:(NSString*)description{
self = [super init];
if (self) {
self.bookTitle = [bookTitle copy];
self.author = [author copy];
self.description = [uri description];
}
return self;
}
+(NSArray*)listOfBooks:(NSArray*)jsonWithBooks{
NSMutableArray *elements = [NSMutableArray new];
for (NSDictionary *dictElment in jsonRespnse){
Books *booksData = [[Books alloc] initWithBook:[dictElment objectForKey:@"bookTitle"]
title:[dictElment objectForKey:@"author"]
description:[dictElment objectForKey:@"description"]];
[elements addObject:booksData];
}
return [NSArray arrayWithArray:elements];
}

在我的 Objective-C 代码中,我调用超类"+(NSArray*)listOfBooks:(NSArray*)jsonWithBooks"来生成对象的 NSArray。但我还没有在 Swift 上找到一个等价物。你们中的任何人都知道做这样的事情的最佳选择是什么?

我正在尝试使用@Alexander示例,但我的项目在以下行崩溃:

let inventoryBooks = Book.books(fromDictArray: json .object(forKey: "books") as! [[String : String]] )

我检查了这个类型:

json .object(forKey: "books")

如下:

let arrayOfBooks = json .object(forKey: "books")
if arrayOfBooks is NSArray {
print("nsarray")
}
if arrayOfBooks is [[String:String]] {
print("string:string")
}
if arrayOfBooks is NSDictionary {
print("NSDic")
}

并且正在打印 nsarray

我的问题。我做错了什么,还是需要更改此函数的签名:

static func books(fromDictArray array: [[String: String]]) -> [Book?] {
return array.map(Book.init)
}

此 json 响应示例:

{
books =     (
{
caption = "";
"display_sizes" =(
{
name = thumb;
uri = "https://someUrl.com/img.jpg";
}
);
id = 123;
"max_dimensions" =             {
height = 4912;
width = 7360;
};
title = "Learning Swift";
author = "Some guy"
}
{
caption = "";
"display_sizes" =(
{
name = thumb;
uri = "https://someUrl.com/img.jpg";
}
);
id = 123;
"max_dimensions" =             {
height = 4912;
width = 7360;
};
title = "Swift";
author = "me meme"
}
)
}

以下是我用惯用 Swift 编写这段代码的方式:

struct Book {
let title: String
let author: String
let description: String
/* an implicit member wise initializer is generated,
which would otherwise look something like this:
init(title: String, author: String, description: String) {
self.title = title
self.author = author
self.description = description  
} */
}
// Initialization from Dictionaries
extension Book {
init?(fromDict dict: [String: Any]) {
guard
let title = dict["bookTitle"] as? String,
let author = dict["author"] as? String,
let description = dict["description"] as? String
else { return nil }
self.init(
title: title,
author: author,
description: description
)
}
static func books(fromDictArray array: [[String: Any]]) -> [Book?] {
return array.map(Book.init)
}
}

以下是一些值得注意的要点:

  1. Book是一个结构体。对一本书如此宽泛的描述不需要支持身份的概念。也就是说,你的书名为"哈利波特",由"J.K.罗琳"描述",可以认为与我的书具有相同的价值。显然没有必要(还)区分你的书的身份和我的身份。

  2. Book有一个隐式的成员初始值设定项init(title:author:description:)它只是将其字段初始化为给定的参数。

  3. 进行了扩展,将所有与字典相关的任务划分为一个单元。

  4. 一个可失败的初始值设定项,init?(fromDictArray:)被制作,它根据给定的字典(大概是从你的 JSON 创建的)返回一本新书。此初始值设定项是容错的。如果提供的字典无效,则初始值设定项将仅返回nil,而不会使程序崩溃。

  5. Book结构体books(fromDictArray:)上创建了一个static方法,它将创建一个可选书籍([Book?],又名Array<Optional<Book>>给定字典的数组。然后,此方法的使用者的工作是随心所欲地处理nil值,即由无效字典产生的值。

    • 他们可以忽略nil书:

      let books = Book.books(fromDictArray: myDictArray).flatMap{$0}
      
    • 如果找到nil书,它们可能会崩溃:

      let books = Book.books(fromDictArray: myDictArray) as! [Book]
      
    • 或者他们可以以某种独特的方式处理 nil 情况:

      let books = Book.books(fromDictArray: myDictArray).map{ book in
      if book == nil {
      print("A nil book was found")
      }
      }
      

正如Dan已经想到的那样,Swift 等价物将是一个class func

class func listOfBooks(jsonWithBooks: [NSDictionary]) -> [Book] {
var books = [Book]()
for json in jsonWithBooks {
let book = Book(
book: json["bookTitle"]!,        
author: json["author"]!,        
description: json["description"]!
)
books.append(book) 
}
return books
}

最新更新