我正在iOS中尝试使用SQlite.Swift,而我正试图从SQLite数据库中的表中随机选择一行。
该表格为movies
,其列为movieID
,title
genre
和seen
。
问题:
电影应该随机挑选,但一旦我将seen
设置为“是”,就不应再挑选它们了。
func randomRow() -> Int {
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory,
.userDomainMask, true)
.first!
let database = try! Connection("\(path)/movies.sqlite3")
var randomRow = Int(arc4random_uniform(UInt32(try!
database.scalar(movies.where(seen != "yes")
.select(movieID.distinct.count)))))
while previousNumber == randomRow {
randomRow = Int(arc4random_uniform(UInt32(try!
database.scalar(movies.where(seen != "yes")
.select(movieID.distinct.count)))))
}
previousNumber = randomRow
return randomRow
}
let destRow = randomRow()
现在我想使用从表中捕获的随机行号来引导随机电影的title
和genre
成let
(“dispMovie”和“movieGenre” )输出到UITextField
。
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory,
.userDomainMask, true)
.first!
let database = try! Connection("\(path)/filme.sqlite3")
for movie in try! database.prepare(
self.movies.where(
seen != "yes" && movieID == "\(destRow)")) {
dispMovie = movie[title]
movieGenre = movie[genre]
}
outputTextField.text = "\(dispMovie), \(movieGenre)"
此代码工作正常。唯一的问题是我的seen
电影仍然会被曝光,因为我在随机行函数中有.count
。
我也试过用这个调用Raw SQLite:
let newMovie = try! database.scalar(
"SELECT title, genre FROM movies WHERE seen != yes
ORDER BY RANDOM() LIMIT 1") as! String
outputTextField.text = newMovie
但是这只显示标题而不是类型,并且无法在额外的行中查找类型,因为电影是从随机行中选取的。我试图在原始代码中引用电影标题,但这会使应用程序崩溃。
感谢您的帮助和提示。
答案 0 :(得分:0)
没有圣诞节,直到完成!
经过几天思考并突然碰到墙壁,我想起了古老的while
循环。事实证明这是有效的,所以我把它作为我自己问题的答案:
忘掉randomRow()
。不需要这个。我首先关注了SQLite RAW,并继续使用scalar
库中的where
,select
和SQLite.Swift
。这终于让我这样:
发布我的整个UIViewController,以便您自己测试:
class TestView: UIViewController {
//Table
let movies = Table("movies")
//Expressions
let movieId = Expression<String>("ID")
let movieTitle = Expression<String>("movieTitle")
let genre = Expression<String>("genre")
let seen = Expression<String>("seen")
//to find with database connection
var randomMovie = String()
var movieDetails = [String]()
//Array of all movies seen
var seenMovies = [String]()
//TestLabel to check everything
@IBOutlet weak var testLabel: UILabel!
@IBAction func testButton(_ sender: Any) {
//Open database connection
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true
).first!
let database = try! Connection("\(path)/movies.sqlite3")
//Check column "seen" and add all movie Titles to Array seenMovies
for movie in try! database.prepare(self.movies.where(seen == "yes")) {
self.seenMovies.append(movie[movieTitle])
}
//Select random row from movies Table with SQLite RAW as String
self.randomMovie = "\(try! database.scalar("SELECT movieTitle FROM movies WHERE seen != yes ORDER BY RANDOM() LIMIT 1"))"
//Create Array of details for that randomly picked movie
//Use scalar, where and select to find details from the picked movie above
self.movieDetails = ["\(randomMovie!)",
"\(try! database.scalar(movies.where(movieTitle == "\(randomMovie!)").select(genre)))"]
//And here's the "unique" thing...
//while randomMovie is also an element in seenMovies, loop until it's not
while seenMovies.contains("\(randomMovie!)") {
randomMovie = "\(try! database.scalar("SELECT movieTitle FROM movies WHERE seen != yes ORDER BY RANDOM() LIMIT 1"))"
}
//let testLabel show the results and see that no seen movie will be picked
testLabel.text = "\(details)\n\n\(erraten)"
//To prevent the Array from being appended over and over:
self.seenMovies.removeAll()
}
}
由于我仍然认为自己是初学者(在10月开始编码&#39; 17),如果可能,请随意优化。我所有的测试都进行得很顺利,当转向&#34;看到&#34;。
时,没有重复的电影答案 1 :(得分:0)
找到了SQLite.Swift issue在2016年提交的解决方案。
DataArray