【发布时间】:2020-04-08 09:35:55
【问题描述】:
我希望视图像 Apple maps UI Tableview 当您单击地图注释时,UI Tableview 会随着加载的信息向上移动并且很流畅。我创建了一个 UITableView 来从 Yelp API 和 Firebase 数据库加载数据。虽然我确实在 UI Tableview 中加载了数据,但 tableview 的移动似乎有些不稳定。例如,当我第一次单击地图注释时,UI Tableview 会弹出,但在随机位置,然后在 Yelp API 加载后,它会再次移动到其默认位置。另一件事是,如果我在 Yelp API 加载之前使用滑动手势,UI Tableview 将相应移动,但随后在 Yelp API 数据加载时重置为其原始位置,然后我必须重做滑动手势。
这个tableview有很多部分,所以我将提供我使用的代码片段列表:
注意:UI Tableview(locationInfoViews)在ViewDidLoad中配置
向上/向下滑动
func configureGestureRecognizer() {
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeGesture))
swipeUp.direction = .up
addGestureRecognizer(swipeUp)
let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeGesture))
swipeDown.direction = .down
addGestureRecognizer(swipeDown)
}
func animateInputView(targetPosition: CGFloat, completion: @escaping(Bool) -> ()) {
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {self.frame.origin.y = targetPosition}, completion: completion)
}
// MARK: - Handlers
@objc func handleSwipeGesture(sender: UISwipeGestureRecognizer) {
if sender.direction == .up {
if expansionState == .Disappeared {
animateInputView(targetPosition: self.frame.origin.y - 100) { (_) in
self.expansionState = .NotExpanded
}
}
if expansionState == .NotExpanded {
animateInputView(targetPosition: self.frame.origin.y - 200) { (_) in
self.expansionState = .PartiallyExpanded
}
}
if expansionState == .PartiallyExpanded {
animateInputView(targetPosition: self.frame.origin.y - 250) { (_) in
self.expansionState = .FullyExpanded
}
}
} else {
if expansionState == .FullyExpanded {
animateInputView(targetPosition: self.frame.origin.y + 250) { (_) in
self.expansionState = .PartiallyExpanded
}
}
if expansionState == .PartiallyExpanded {
animateInputView(targetPosition: self.frame.origin.y + 200) { (_) in
self.expansionState = .NotExpanded
}
}
if expansionState == .NotExpanded {
animateInputView(targetPosition: self.frame.origin.y + 100) { (_) in
self.expansionState = .Disappeared
}
}
}
}
选择注释时,来自 Yelp 和 Firebase 的信息将被加载到位置信息视图中,并且动画应该向上移动
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
self.locationPosts.removeAll()
self.inLocationInfoMode = true
if view.annotation is MKUserLocation {
print("selected self")
} else {
self.selectedAnnotation = view.annotation as? Annotation
let coordinates = selectedAnnotation.coordinate
let coordinateRegion = MKCoordinateRegion(center: coordinates, latitudinalMeters: 1000, longitudinalMeters: 100)
mapView.setRegion(coordinateRegion, animated: true)
self.locationInfoViews.locationTitle = self.selectedAnnotation.title
// Fetch Location Post
guard let currentUid = Auth.auth().currentUser?.uid else {return}
LOCATION_REF.child(self.selectedAnnotation.title).child(currentUid).observe(.childAdded) { (snapshot) in
let postId = snapshot.key
Database.fetchLocationPost(with: postId) { (locationPost) in
self.locationPosts.append(locationPost)
self.locationPosts.sort { (post1, post2) -> Bool in
return post1.creationDate > post2.creationDate
}
self.locationInfoViews.locationResults = self.locationPosts
// self.locationInfoViews.tableView.reloadData()
// Fetch Location Information
guard let locationName = locationPost.locationName else {return}
guard let locationAddress = locationPost.address else {return}
let locationRef = COORDINATES_REF.child(locationName).child(locationAddress)
locationRef.child("mainTypeOfPlace").observe(.value) { (snapshot) in
guard let mainTypeOfPlace = snapshot.value as? String else {return}
// self.locationInfoViews.typeOfPlace = mainTypeOfPlace
locationRef.child("shortAddress").observe(.value) { (snapshot) in
guard let address1 = snapshot.value as? String else {return}
locationRef.child("city").observe(.value) { (snapshot) in
guard let city = snapshot.value as? String else {return}
locationRef.child("state").observe(.value) { (snapshot) in
guard let state = snapshot.value as? String else {return}
locationRef.child("countryCode").observe(.value) { (snapshot) in
guard let country = snapshot.value as? String else {return}
// fetch Yelp API Data
self.service.request(.match(name: locationName, address1: address1, city: city, state: state, country: country)) {
(result) in
switch result {
case .success(let response):
let businessesResponse = try? JSONDecoder().decode(BusinessesResponse.self, from: response.data)
let firstID = businessesResponse?.businesses.first?.id
self.information.request(.BusinessID(id: firstID ?? "")) {
(result) in
switch result {
case .success(let response):
if let jsonResponse = try? JSONSerialization.jsonObject(with: response.data, options: []) as? [String: Any] {
// print(jsonResponse)
if let categories = jsonResponse["categories"] as? Array<Dictionary<String, AnyObject>> {
var mainCategory = ""
for category in categories {
mainCategory = category["title"] as? String ?? ""
break
}
self.locationInfoViews.typeOfPlace = mainCategory
}
let price = jsonResponse["price"] as? String ?? ""
if let hours = jsonResponse["hours"] as? Array<Dictionary<String, AnyObject>> {
for hour in hours {
let isOpen = hour["is_open_now"] as? Int ?? 0
if isOpen == 1 {
let attributedText = NSMutableAttributedString(string: "open ", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x066C19)])
attributedText.append(NSAttributedString(string: " \(price)", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.black]))
self.locationInfoViews.hoursLabel.attributedText = attributedText
} else {
let attributedText = NSMutableAttributedString(string: "closed ", attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.red])
attributedText.append(NSAttributedString(string: " \(price)", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.darkGray]))
self.locationInfoViews.hoursLabel.attributedText = attributedText
}
}
}
}
case .failure(let error):
print("Error: \(error)")
}
}
case .failure(let error):
print("Error: \(error)")
}
}
}
}
}
}
}
self.locationInfoViews.tableView.reloadData()
}
}
// enable the goButton
if inLocationInfoMode {
locationInfoViews.goButton.isEnabled = true
locationInfoViews.coordinates = selectedAnnotation.coordinate
}
// the movement of the location info view
if self.locationInfoViews.expansionState == .Disappeared {
self.locationInfoViews.animateInputView(targetPosition: self.locationInfoViews.frame.origin.y - 335) { (_) in
self.locationInfoViews.expansionState = .PartiallyExpanded
}
}
}
}
【问题讨论】:
-
一段视频在这种情况下会有所帮助
-
您是否确保在后台线程而不是主线程上进行 api 调用?
-
我在主线程上做,因为我不知道如何在后台线程上做。
-
@Josh 对在后台线程上进行 API 调用进行一些研究应该会让您有一个良好的开端。
-
我对此很陌生,一直在研究如何解决这个问题,但在实施过程中遇到了困难。对我编写的代码的任何建议将不胜感激。谢谢!
标签: ios swift api uitableview