我有以下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)
}
}
以下是一些值得注意的要点:
Book
是一个结构体。对一本书如此宽泛的描述不需要支持身份的概念。也就是说,你的书名为"哈利波特",由"J.K.罗琳"描述",可以认为与我的书具有相同的价值。显然没有必要(还)区分你的书的身份和我的身份。Book
有一个隐式的成员初始值设定项init(title:author:description:)
它只是将其字段初始化为给定的参数。进行了扩展,将所有与字典相关的任务划分为一个单元。
一个可失败的初始值设定项,
init?(fromDictArray:)
被制作,它根据给定的字典(大概是从你的 JSON 创建的)返回一本新书。此初始值设定项是容错的。如果提供的字典无效,则初始值设定项将仅返回nil
,而不会使程序崩溃。在
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
}