当我通过错误进入此控制器时,我的应用程序正在崩溃:因未捕获的异常终止应用程序' NSInternalInconsistencyException',原因:'尝试将第0行插入第0部分,但是有更新后第0部分只有0行' 所以我对tableView有问题,这个类是这样的:
import UIKit
import MapKit
import CoreLocation
import GoogleMaps
import GooglePlaces
import Social
import AVFoundation
private let resueIdentifier = "MyTableViewCell"
extension UIViewController {
func present(viewController : UIViewController, completion : (() -> ())? = nil ){
if let presented = self.presentedViewController {
presented.removeFromParentViewController()
}
self.present(viewController, animated: true, completion: completion)
}
}
class CourseClass2: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
struct User {
var name: String
var images: UIImage
var type: String
}
var previuosViewTappedButtonsArray = [String]()
var locationManager:CLLocationManager?
let minimumSpacing : CGFloat = 15 //CGFloat(MAXFLOAT)
let cellWidth: CGFloat = 250
let radius = 5000 // 5km
var category : QCategoryy?
var currentLocation : CLLocationCoordinate2D?
var places: [QPlace] = []
var isLoading = false
var response : QNearbyPlacesResponse?
var rows = 0
var users = [User]()
override func viewDidLoad() {
super.viewDidLoad()
self.title = category?.name
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
determineMyCurrentLocation()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
rows = 0
tableView.reloadData()
insertRowsMode3()
category?.markView()
}
@IBAction func refreshTapped(_ sender: Any) {
rows = 0
tableView.reloadData()
insertRowsMode3()
}
func canLoadMore() -> Bool {
if isLoading {
return false
}
if let response = self.response {
if (!response.canLoadMore()) {
return false
}
}
return true
}
func loadPlaces(_ force:Bool) {
if !force {
if !canLoadMore() {
return
}
}
print("load more")
isLoading = true
NearbyPlaces.getNearbyPlaces(by: category?.name ?? "food", coordinates: currentLocation!, radius: radius, token: self.response?.nextPageToken, completion: didReceiveResponse)
}
func didReceiveResponse(response:QNearbyPlacesResponse?, error : Error?) -> Void {
if let error = error {
let alertController = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
let actionDismiss = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
let actionRetry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
})
alertController.addAction(actionRetry)
alertController.addAction(actionDismiss)
DispatchQueue.main.async {
self.present(viewController: alertController)
}
}
if let response = response {
self.response = response
if response.status == "OK" {
if let placesDownloaded = response.places {
places.append(contentsOf: placesDownloaded)
}
self.tableView?.reloadData()
} else {
let alert = UIAlertController.init(title: "Error", message: response.status, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction.init(title: "Retry", style: .default, handler: { (action) in
DispatchQueue.main.async {
self.loadPlaces(true)
}
}))
self.present(viewController: alert)
}
isLoading = false
}
else {
print("response is nil")
}
}
func insertRowsMode2() {
for i in 0..<places.count {
insertRowMode2(ind: i, usr: places[i])
}
}
func insertRowMode2(ind:Int,usr:QPlace) {
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
}
func insertRowsMode3() {
rows = 0
insertRowMode3(ind: 0)
}
func insertRowMode3(ind:Int) {
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
guard ind < places.count-1 else { return }
DispatchQueue.main.asyncAfter(deadline: .now()+0.20) {
self.insertRowMode3(ind: ind+1)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return places.count /* rows */
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
let place = places[indexPath.row]
cell.update(place: place)
if indexPath.row == places.count - 1 {
loadPlaces(false)
}
/* let user = users[indexPath.row]
cell.selectionStyle = .none
cell.myImage.image = user.images
cell.myLabel.text = user.name
cell.myTypeLabel.text = user.type */
return (cell)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
UIView.animate(withDuration: 0.2, animations: {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
})
performSegue(withIdentifier: "goToLast" , sender: users[indexPath.row])
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCellEditingStyle.delete {
places.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
func didReceiveUserLocation(_ userLocation:CLLocation) {
currentLocation = userLocation.coordinate
loadPlaces(true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToLast" && sender is IndexPath {
let dvc = segue.destination as! FinalClass
dvc.index = (sender as! IndexPath).row
dvc.places = places
dvc.userLocation = currentLocation
/* guard let vc = segue.destination as? FinalClass else { return }
let guest = segue.destination as! FinalClass
if let user = sender as? User {
*/
}
}
@IBAction func IndTapped(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func socialShare(_ sender: Any) {
//Alert
let alert = UIAlertController(title: "Share", message: "First share!", preferredStyle: .actionSheet)
//First action
let actionOne = UIAlertAction(title: "Share on Facebook", style: .default) { (action) in
//Checking if user is connected to Facebook
if SLComposeViewController.isAvailable(forServiceType: SLServiceTypeFacebook)
{
let post = SLComposeViewController(forServiceType: SLServiceTypeFacebook)!
post.setInitialText("First")
post.add(UIImage(named: "uround logo.png"))
self.present(post, animated: true, completion: nil)
} else {self.showAlert(service: "Facebook")}
}
let actionThree = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
//Add action to action sheet
alert.addAction(actionOne)
alert.addAction(actionThree)
//Present alert
self.present(alert, animated: true, completion: nil)
}
func showAlert(service:String)
{
let alert = UIAlertController(title: "Error", message: "You are not connected to \(service)", preferredStyle: .alert)
let action = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil)
alert.addAction(action)
present(alert, animated: true, completion: nil)
}
}
extension CourseClass2: CLLocationManagerDelegate {
func determineMyCurrentLocation() {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
locationManager?.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
manager.stopUpdatingLocation()
print("user latitude = \(userLocation.coordinate.latitude)")
print("user longitude = \(userLocation.coordinate.longitude)")
didReceiveUserLocation(userLocation)
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error \(error)")
errorGettingCurrentLocation(error.localizedDescription)
}
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse || status == .authorizedAlways {
locationManager?.startUpdatingLocation()
//locationManager.startUpdatingHeading()
} else if status == .denied || status == .restricted {
errorGettingCurrentLocation("Location access denied")
}
}
func errorGettingCurrentLocation(_ errorMessage:String) {
let alert = UIAlertController.init(title: "Error", message: errorMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil))
present(alert, animated: true, completion: nil)
}
}
添加一个断点我发现粉碎在这个函数中:
func insertRowMode3(ind:Int) {
let indPath = IndexPath(row: ind, section: 0)
rows = ind + 1
tableView.insertRows(at: [indPath], with: .right)
guard ind < places.count-1 else { return }
DispatchQueue.main.asyncAfter(deadline: .now()+0.20) {
self.insertRowMode3(ind: ind+1)
}
}
正好在这一行:
tableView.insertRows(at: [indPath], with: .right)
我不知道如何修改这些功能来解决问题,我已经查看了其他问题,但没有找到有用的东西。 与此UIViewController一起使用的其他类是:
struct QCategoryy {
var name:String
init(name:String) {
self.name = name
}
}
extension QCategoryy: ExpressibleByStringLiteral {
init(stringLiteral value: String) {
self.name = value
}
init(unicodeScalarLiteral value: String) {
self.init(name: value)
}
init(extendedGraphemeClusterLiteral value: String) {
self.init(name: value)
}
}
和
import UIKit
import CoreLocation
private let geometryKey = "geometry"
private let locationKey = "location"
private let latitudeKey = "lat"
private let longitudeKey = "lng"
private let nameKey = "name"
private let openingHoursKey = "opening_hours"
private let openNowKey = "open_now"
private let vicinityKey = "vicinity"
private let typesKey = "types"
private let photosKey = "photos"
class QPlace: NSObject {
var location: CLLocationCoordinate2D?
var name: String?
var photos: [QPhoto]?
var vicinity: String?
var isOpen: Bool?
var types: [String]?
init(placeInfo:[String: Any]) {
// coordinates
if let g = placeInfo[geometryKey] as? [String:Any] {
if let l = g[locationKey] as? [String:Double] {
if let lat = l[latitudeKey], let lng = l[longitudeKey] {
location = CLLocationCoordinate2D.init(latitude: lat, longitude: lng)
}
}
}
// name
name = placeInfo[nameKey] as? String
// opening hours
if let oh = placeInfo[openingHoursKey] as? [String:Any] {
if let on = oh[openNowKey] as? Bool {
isOpen = on
}
}
// vicinity
vicinity = placeInfo[vicinityKey] as? String
// types
types = placeInfo[typesKey] as? [String]
// photos
photos = [QPhoto]()
if let ps = placeInfo[photosKey] as? [[String:Any]] {
for p in ps {
photos?.append(QPhoto.init(photoInfo: p))
}
}
}
func getDescription() -> String {
var s : [String] = []
if let name = name {
s.append("Name: \(name)")
}
if let vicinity = vicinity {
s.append("Vicinity: \(vicinity)")
}
if let types = types {
s.append("Types: \(types.joined(separator: ", "))")
}
if let isOpen = isOpen {
s.append(isOpen ? "OPEN NOW" : "CLOSED NOW")
}
return s.joined(separator: "\n")
}
func heightForComment(_ font: UIFont, width: CGFloat) -> CGFloat {
let desc = getDescription()
let rect = NSString(string: desc).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(rect.height)
}
}
答案 0 :(得分:0)
您必须先更新UITableViewDataSource
,然后插入行。
插入行时的业务顺序:
1.确保numberOfRowsInSection
返回新的增值值
2.确保cellForRowAtIndexPath
可以在新索引路径上提供单元格的数据
3.实际在表格视图中插入行