我是初学iOS开发人员(这实际上是我第一次尝试使用iOS应用)。我正在制作的应用程序应该在地图上显示污染程度。我想要的是设置一个滑块并根据滑块设置显示特定时间的污染程度。
我最初的,显然是错误的方法是,每当滑块更改并更改func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
内显示的结果时,更改fetchResultsController获取请求谓词。这种方法的问题在于,更改获取请求似乎并没有调用controllerDidChangeContent
函数。似乎只有在向db添加新元素时才会触发此操作。制作这种动态更改获取请求的规范解决方案是什么?
我在下面介绍了完成上述工作的课程。
CoreDataViewController
import UIKit
import CoreData
class CoreDataViewController: UIViewController, NSFetchedResultsControllerDelegate {
// MARK: Properties
var fetchedResultsController : NSFetchedResultsController<NSFetchRequestResult>? {
didSet {
// Whenever the frc changes, execute the search and
// reload the data
print("fetchedResultsController did set")
fetchedResultsController?.delegate = self
executeSearch()
}
}
// MARK: Initializers
init?(_ coder: NSCoder, fetchedResultsController fc : NSFetchedResultsController<NSFetchRequestResult>) {
fetchedResultsController = fc
super.init(coder: coder)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
extension CoreDataViewController {
func executeSearch() {
if let fc = fetchedResultsController {
do {
try fc.performFetch()
} catch let e as NSError {
print("Error while trying to perform a search: \n\(e)\n\(fetchedResultsController)")
}
}
}
}
MapViewController(扩展CoreDataViewController)
import UIKit
import GoogleMaps
import CoreData
class MapViewController: CoreDataViewController {
// var mapView: GMSMapView!
@IBOutlet weak var testButton: UIBarButtonItem!
@IBOutlet weak var timestampSlider: UISlider!
override func loadView() {
// Get the stack
let delegate = UIApplication.shared.delegate as! AppDelegate
let stack = delegate.stack
// Create a fetchrequest
let fr = NSFetchRequest<NSFetchRequestResult>(entityName: "Measurement")
fr.sortDescriptors = [NSSortDescriptor(key: "fromDatetime", ascending: true)]
fr.predicate = NSPredicate(format: "fromDatetime = %@", argumentArray: [2])
// Create the FetchedResultController
fetchedResultsController = NSFetchedResultsController(fetchRequest: fr, managedObjectContext: stack.context,
sectionNameKeyPath: nil, cacheName: nil)
let measurements = fetchedResultsController?.fetchedObjects as! [Measurement]
// Create a GMSCameraPosition that tells the map to display the
// coordinate latitude: 50.0646501, longitude: 19.9449799 at zoom level 6.
let camera = GMSCameraPosition.camera(withLatitude: 50.0646501, longitude: 19.9449799, zoom: 14.0)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
view = mapView
_ = measurements.flatMap({(m: Measurement) -> Void in
print(m.fromDatetime)
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: m.latitude, longitude: m.longitude)
marker.title = "Measurement"
marker.snippet = String(format: "pm10: %f, pm25: %f", m.pm10, m.pm25)
marker.map = mapView
})
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.isToolbarHidden = true
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func testButtonAction(_ sender: Any) {
// Get the stack
let delegate = UIApplication.shared.delegate as! AppDelegate
let stack = delegate.stack
_ = Measurement(sensorId: 0, fromDatetime: 2, pm10: 0.6, pm25: 0.3, airQualityIndex: 0.8, latitude: 50.0626402, longitude: 19.9385001, source: "Airly", windDeg: 0.9, windSpeed: 23.0, insertInto: stack.context)
}
@IBAction func timestampSliderAction(_ sender: Any) {
if self.timestampSlider == nil {
return
}
let sliderValue = floor(self.timestampSlider.value)
print(sliderValue)
let delegate = UIApplication.shared.delegate as! AppDelegate
let stack = delegate.stack
let fr = NSFetchRequest<NSFetchRequestResult>(entityName: "Measurement")
fr.sortDescriptors = [NSSortDescriptor(key: "fromDatetime", ascending: true)]
fr.predicate = NSPredicate(format: "fromDatetime = %@", argumentArray: [sliderValue])
// Create the FetchedResultController
fetchedResultsController = NSFetchedResultsController(fetchRequest: fr, managedObjectContext: stack.context,
sectionNameKeyPath: nil, cacheName: nil)
// alternative solution without creating new NSFetchedResultsController
// fetchedResultsController?.fetchRequest.predicate = NSPredicate(format: "fromDatetime = %@", argumentArray: [sliderValue])
// executeSearch()
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
print("controllerDidChangeContent called")
let measurements = fetchedResultsController?.fetchedObjects as! [Measurement]
let mapView = view as! GMSMapView
_ = measurements.flatMap({(m: Measurement) -> Void in
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: m.latitude, longitude: m.longitude)
marker.title = "Measurement"
marker.snippet = String(format: "pm10: %f, pm25: %f", m.pm10, m.pm25)
marker.map = mapView
})
}
}
答案 0 :(得分:0)
解决方案结果非常简单。要触发Galera
,我只需在谓词更改后调用public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String server = "http://server.tld";
String subURI = request.getRequestURI().split("/ProxyServlet")[1];
System.out.println("ProxyServlet: " + server + subURI);
URL remoteServer = new URL(server + subURI);
HttpURLConnection connection = (HttpURLConnection) remoteServer.openConnection();
//somehow apply request to remoteServer and receive response
}
。我不确定这是否是正式的方式,但它对我有用。