【问题标题】:App crashs trying to get a view from segue (swift - iOS)试图从 segue 获取视图的应用程序崩溃(swift - iOS)
【发布时间】:2017-09-22 11:32:12
【问题描述】:

所以,我正在构建一个使用 OMDB API 从 IMDB 搜索电影的应用。有两种方法可以通过电影标题搜索,返回:海报、标题、类型、年份、imdbID。另一种方法是通过 imdbTitle 搜索,它只返回一部电影,其中包含更多内容,如演员、导演等。我的搜索工作正常,当我在搜索栏上输入电影标题时,我会得到一个电影列表。但是,当我单击电影以显示包含电影详细信息的视图时,我的应用程序崩溃了。我在代码上打印了一些内容,看看它走了多远,当我尝试执行我的 getMovieByID 函数时它崩溃了。

这就是我想要做的......

使用 Alamofire 在 OMDB API 上通过其 id 获取电影:

func getMovieByIdJSON(imdbID: String, completionHandler: @escaping (Dictionary<String, String>) -> Void) {

let url = "https://www.omdbapi.com/?i=\(imdbID)"

Alamofire.request(url).responseJSON {
    response in

    if let json = response.result.value {
        completionHandler((json as? Dictionary<String, String>)!)
    } 
  }

}

然后,我有我的电影课:

class Movie {

var poster, title, runtime, director, actors, genre,
plot, production, year, imdbID, imdbRating : String?

init(poster: String?, title: String?, runtime: String?, director: String?, actors: String?, genre: String?, plot: String?, production: String?, year: String?, imdbID: String?, imdbRating: String?) {

    if let isPoster = poster { self.poster = isPoster }
    else { self.poster = nil }

    if let isTitle = title { self.title = isTitle }
    else { self.title = nil }

    if let isRuntime = runtime { self.runtime = isRuntime }
    else { self.runtime = nil }

    if let isDirector = director { self.director = isDirector }
    else { self.director = nil }

    if let isActors = actors { self.actors = isActors }
    else { self.actors = nil }

    if let isGenre = genre { self.genre = isGenre }
    else { self.genre = nil }

    if let isPlot = plot { self.plot = isPlot }
    else { self.plot = nil }

    if let isProduction = production { self.production = isProduction }
    else { self.production = nil }

    if let isYear = year { self.year = isYear }
    else { self.year = nil }

    if let isImdbID = imdbID { self.imdbID = isImdbID }
    else { self.imdbID = nil }

    if let isImdbRating = imdbRating { self.imdbRating = isImdbRating }
    else { self.imdbRating = nil }

  }
}

My MovieDAO 通过 ID 获取电影:

class MovieDAO {

func getMovieByID(imdbID: String, completionHandler: @escaping (Movie) -> ()) {

    getMovieByIdJSON(imdbID: imdbID, completionHandler: {
        (dict) in

        let movie: Movie = Movie(poster: dict["Poster"]!, title: dict["Title"]!, runtime: dict["Runtime"]!, director: dict["Director"]!, actors: dict["Actors"]!, genre: dict["Genre"]!, plot: dict["Plot"]!, production: dict["Production"]!, year: dict["Year"]!, imdbID: dict["imdbID"]!, imdbRating: dict["imdbRating"]!)

        completionHandler(movie)
    })
  }

}

最后,可能是导致这种混乱的代码......

在我的 SearchTableViewController 上,我准备了这个 segue:

let searchSegue = "segueFromSearch"

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let destination = segue.destination as? MovieViewController
    let searchIndex = tableView.indexPathForSelectedRow?.row
    let selectedImdbID = self.movies[searchIndex!].imdbID

    print("IMDB_ID: \(String(describing: selectedImdbID))")

    if segue.identifier == searchSegue {
        destination?.movieImdbID = selectedImdbID!
        print("Debug print: I get til here")
    }
}

显示电影详情的视图有这个 MovieViewController:

import UIKit

class MovieViewController: UIViewController {

let DAO: MovieDAO = MovieDAO()
var movie: Movie? = nil
var movieImdbID: String?


override func viewDidLoad() {
    super.viewDidLoad()

    print("Movie Controller view didLoad - before get the movie function")

    DAO.getMovieByID(imdbID: self.movieImdbID!, completionHandler: {
        movieResult in

        print("Imdb self.movie: \(String(describing: self.movie))")
        self.movie = movieResult

        print("after self.movie")

    }) 
  }
}

我模拟了一个看电影细节的尝试,我的控制台输出是这样的:

2017-04-25 09:29:17.016079-0300 Favorite Movies[14492:460113] [MC] Reading from private effective user settings.
IMDB_ID: Optional("tt0437236")
Debug print: I get til here
Movie Controller view didLoad - before get the movie function
(lldb) 

所以,我想问题出在我的 MovieViewController 中的这个函数上,因为应用程序在尝试执行它时会崩溃。知道我做错了什么吗?我在这里想念什么?

PS.:对于一堆代码,我很抱歉,但我试图解释并显示崩溃之前的所有路径,因为也许问题不在我想的地方。

更新:##

xcode 显示: [![xcode][1]][1]

更新 2

正如@unkg 所问,这里是我的 getMovieByIdJSON 中的第 13 行:

PS.:我注意到我的 segue 函数正在传递(如控制台上打印的)“Optional("tt0944849")”。那正确吗?这个可选的打印也作为字符串的一部分传递?

【问题讨论】:

  • 错误信息是什么?
  • 任何崩溃日志?
  • 您确定 segue.destination 是您的 MovieViewController 吗?我建议在prepare(for segue:) 中放置一个断点并检查变量并检查它们是否为nil
  • @ChanJingHong 它不是零,如您所见,在我的 segue 准备功能上,它会在控制台上打印电影 ID。我的意思是,此时有一个电影 ID。但我不知道为什么当我调用我的函数 getMovieByID 从prepare segue 接收此ID 时,应用程序崩溃。
  • @Sweeper 我更新了错误图片

标签: ios swift


【解决方案1】:

查看示例 omdbapi 响应,我认为您不能可靠地转换为 Dictionary&lt;String, String&gt;。注意Ratings: [] 是一个空的Array。您可能需要转换为Dictionary&lt;String, AnyObject&gt;。我也会小心展开的力。

如果 selectedImdbID 打印为可选,请务必打开包装。

https://www.omdbapi.com/?i=tt4649466

{
    "Title": "Kingsman: The Golden Circle",
    "Year": "2017",
    "Rated": "N/A",
    "Released": "29 Sep 2017",
    "Runtime": "N/A",
    "Genre": "Action, Adventure, Comedy",
    "Director": "Matthew Vaughn",
    "Writer": "Jane Goldman (screenplay), Matthew Vaughn (screenplay), Mark Millar (characters), Dave Gibbons (characters)",
    "Actors": "Taron Egerton, Channing Tatum, Julianne Moore, Pedro Pascal",
    "Plot": "When their headquarters are destroyed and the world is held hostage, the Kingsman's journey leads them to the discovery of an allied spy organization in the US. These two elite secret organizations must band together to defeat a common enemy.",
    "Language": "English",
    "Country": "UK, USA",
    "Awards": "N/A",
    "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BNTBlOWZhZTctOTY0MC00Y2QyLTljMmYtZDkxZDFlMWU4Y2EyXkEyXkFqcGdeQXVyNDg2MjUxNjM@._V1_SX300.jpg",
    "Ratings": [],
    "Metascore": "N/A",
    "imdbRating": "N/A",
    "imdbVotes": "N/A",
    "imdbID": "tt4649466",
    "Type": "movie",
    "DVD": "N/A",
    "BoxOffice": "N/A",
    "Production": "20th Century Fox",
    "Website": "http://www.foxmovies.com/movies/kingsman-the-golden-circle",
    "Response": "True"
}

顺便说一句,我是ObjectMapper 的忠实粉丝。有了它,你可以将你的 Movie 类转换成这样的东西

class Movie: Mappable {
    var poster, title, runtime, director, actors, genre, plot, production, year, imdbID, imdbRating : String?

    required init?(map: Map) {
    }

    func mapping(map: Map) {
        poster    <- map["Poster"]
        title     <- map["Title"]
        runtime   <- map["Runtime"]
        director  <- map["Director"]
        //...etc...
    }
}

【讨论】:

  • +1 表示@dmorrow 响应。您的崩溃与 segue 或任何 iOS 系统调用无关。您的屏幕截图不是决定性的,但 JSON 反序列化是失败的。您可以使用 ObjectMapper 作为库依赖,静态或通过依赖管理器进行更新。或者您可以使用代码生成工具,例如 AhmedAli 的 JSONEXport github.com/Ahmed-Ali/JSONExport(要求您在 XCode 中将他的解决方案构建为 Mac OS 应用程序)
  • 嘿,@dmorrow,谢谢!我听从了你的建议,我正在尝试这样做,但我有一些疑问和另一个错误。你能帮忙吗?这里的问题:stackoverflow.com/questions/43623796/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多