我正在尝试从数据库中的一组值向Cesium映射添加多个baselayers。我想让javascript迭代它们然后添加它们。以下是Cesium的静态代码示例:
var imageryViewModels = [];
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Open\u00adStreet\u00adMap',
iconUrl : Cesium.buildModuleUrl('openStreetMap.png'),
tooltip : 'OpenStreetMap (OSM)',
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : 'https://a.tile.openstreetmap.org/'
});
}
}));
imageryViewModels.push(new Cesium.ProviderViewModel({
name : 'Black Marble',
iconUrl : Cesium.buildModuleUrl('blackMarble.png'),
tooltip : 'outlines of civilization',
creationFunction : function() {
return Cesium.createTileMapServiceImageryProvider({
url : 'https://cesiumjs.org/blackmarble',
credit : 'B Observatory',
flipXY : true
});
}
}));
到目前为止超级简单,一组静态值。这是它变得棘手的地方,我想循环一组值,然后将ProviderViewModels推送到数组。像这样 -
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url // ***** this value always the last value ****
});
}
}));
}
问题是javascript闭包导致我出现问题,我的每个imageryViewModel都是baseLayer.url对象中的最后一个值。铯需要这个功能。有没有办法保持这个函数,但得到迭代的baseLayer.url的值?
答案 0 :(得分:2)
请尝试这个(我还没试过):
var imageryViewModels = [];
baseLayers = HashOfValuesFromDatabase;
for(int i=0; i<baseLayers.length; i++{
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayser[i].toolTip,
creationFunction : (function(i) {
return function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url
});
}
}(i))
}));
}
编辑:正确的语法(感谢emackey)
答案 1 :(得分:2)
Ben Aston的答案是正确的方法。他没有尝试运行它,并且date(DATE_RFC822, time());
在参数列表中非法的后面还有一个额外的分号,并且还有一些问题是他从原始文件中复制粘贴的题。这是更正后的版本,我确实让它运行:
class attendees: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
var tableData = ""
var value:String!
var searchString = ""
var firstname: [String] = []
var lastname: [String] = []
var fullname: [String] = []
var company: [String] = []
var jobtitle: [String] = []
var image: [String] = []
var filteredAppleProducts = [String]()
var resultSearchController = UISearchController()
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
print(value)
searchBar.delegate = self
self.tableView.reloadData()
let nib = UINib(nibName: "vwTblCell2", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "cell2")
}
override func viewDidAppear(_ animated: Bool) {
getTableData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if filteredAppleProducts != []{
return self.filteredAppleProducts.count
}
else
{
if searchString != "[]" {
return self.firstname.count
}else {
return 0
}
}
}
// 3
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell2: TblCell2 = self.tableView.dequeueReusableCell(withIdentifier: "cell2") as! TblCell2
print(filteredAppleProducts)
if filteredAppleProducts != []{
cell2.nameLabel.text = self.filteredAppleProducts[indexPath.row]
return cell2
}
else
{
if searchString != "[]"{
cell2.nameLabel.text = "\(self.firstname[indexPath.row]) \(self.lastname[indexPath.row])"
cell2.companyLabel.text = self.company[indexPath.row]
cell2.jobTitleLabel.text = self.jobtitle[indexPath.row]
let url = URL(string: "https://www.asmserver.co.uk/wellpleased/backend/profileimages/\(self.image[indexPath.row])")
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
cell2.userImage.image = UIImage(data: data!)
}
return cell2
}
}
// 4
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
// 5
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 90
}
func updateSearchResults(){
self.filteredAppleProducts.removeAll(keepingCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %@", searchString)
let array = (self.fullname as NSArray).filtered(using: searchPredicate)
self.filteredAppleProducts = array as! [String]
self.tableView.reloadData()
print(filteredAppleProducts)
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print("searchText \(searchText)")
print(filteredAppleProducts)
searchString = searchText
updateSearchResults()
}
func getTableData(){
self.firstname.removeAll()
self.lastname.removeAll()
self.fullname.removeAll()
self.company.removeAll()
self.jobtitle.removeAll()
self.image.removeAll()
let defaults = UserDefaults()
let userid = defaults.string(forKey: "id")
let url = NSURL(string: "https://www.asmserver.co.uk/wellpleased/backend/searchattendees.php?userid=\(userid!)&eventid=\(value!)")
print(url)
let task = URLSession.shared.dataTask(with: url as! URL) { (data, response, error) -> Void in
if let urlContent = data {
do {
if let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: []) as? [[String:AnyObject]] {
var i = 0
while i < jsonResult.count {
self.firstname.append(jsonResult[i]["firstname"]! as! String)
self.lastname.append(jsonResult[i]["lastname"]! as! String)
let fname = jsonResult[i]["firstname"]! as! String
let lname = jsonResult[i]["lastname"]! as! String
let fullname1 = "\(fname) \(lname)"
self.fullname.append(fullname1)
self.company.append(jsonResult[i]["company"]! as! String)
self.jobtitle.append(jsonResult[i]["jobtitle"]! as! String)
self.image.append(jsonResult[i]["image"]! as! String)
i = i + 1
}
}
} catch {
print("JSON serialization failed")
}
} else {
print("ERROR FOUND HERE")
}
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
self.tableView.isUserInteractionEnabled = true
}
task.resume()
}
}
修复}(i))
参数的原因是因为使用var imageryViewModels = [];
for(var i=0; i<baseLayers.length; i++) {
imageryViewModels.push(new Cesium.ProviderViewModel({
name : baseLayers[i].name,
iconUrl : Cesium.buildModuleUrl(baseLayers[i].iconUrl),
tooltip : baseLayers[i].toolTip,
creationFunction : (function(i) {
return function() {
return Cesium.createOpenStreetMapImageryProvider({
url : baseLayers[i].url
});
};
}(i))
}));
}
作为参数的IIFE(立即调用的函数表达式)。这通过循环每次迭代创建一个新的JavaScript闭包,这是昂贵的,但是是必需的,以便每个单独的url
函数获得它自己的闭包,它具有自己的i
值的副本循环的迭代。如果没有这个,只有一个只有一个create
变量的闭包,当实际调用任何创建函数时,循环很长并且i
的值已达到最大值