简体   繁体   English

如何遍历动态大小的数组并传递可变参数中的参数作为属性?

[英]How to loop through array of dynamic size and pass properties as arguments in variadic function?

I have a bit of an interesting question, and am not sure if what I am wanting to do is possible. 我有一个有趣的问题,不确定我想做什么。 If not, I imagine there is some other workaround for my issue. 如果没有,我想我的问题还有其他解决方法。

I am using Mapbox (MapKit alternative) for iOS. 我正在使用iOS的Mapbox(替代MapKit)。 Mapbox has style layers which let you set different images for different pins on a map. Mapbox具有样式图层,可让您为地图上的不同图钉设置不同的图像。 This is done by setting the layer's iconImageName to a different value depending on the map pin it's dealing with. 这是通过将图层的iconImageName设置为不同的值来完成的,具体取决于它要处理的地图图钉。 The value that is given as the style layer's iconImageName is an NSExpression , in which we pass a format as a string and any other number of NSExpression so that they fit the format. 作为样式层的iconImageName给出的值是NSExpression ,在其中我们将格式传递为字符串和任何其他数量的NSExpression以使其适合格式。 Below is an example of creating a style layer from images that are not dynamic, ie these images are hard-coded into the app. 以下是从动态图像创建样式层的示例,即这些图像被硬编码到应用程序中。

//Create the layer
let ports = MGLSymbolStyleLayer(identifier: "ports", source: source)
//Create a default shape
let defaultShape = NSExpression(forConstantValue: "grayMarker")

//For every pin in the 'ports' layer, we are going to look at its 
//'type' property. If 'type' is equal to the string 'redPin', its image 
//should be the one registered with the name 'redMarker'. If 'type' is 
//equal to the string 'bluePin', its image should be the one registered 
//with the name 'blueMarker'...and so on. If 'type' doesn't match 
//anything outlined here, then set the pin's image to the default 
//shape.
ports.iconImageName = NSExpression(format: "MGL_MATCH(type, 'redPin', %@, 'bluePin', %@, 'greenPin', %@, 'grayPin', %@, %@)", NSExpression(forConstantValue: "redMarker"), NSExpression(forConstantValue: "blueMarker"), NSExpression(forConstantValue: "greenMarker"), NSExpression(forConstantValue: "grayMarker"), defaultShape)

//Add the layer to the map's style
self.mapStyle!.addLayer(ports)

So, this is very easy to do when the information is hard-coded into the app. 因此,当信息被硬编码到应用程序中时,这很容易做到。 The problem is, I have a series of "pin types" that are returned from an API request, that I may need to change down the road. 问题是,我从API请求中返回了一系列“引脚类型”,因此我可能需要进行一些更改。 These pin types have a photoUrl associated with them. 这些引脚类型具有与之关联的photoUrl。

As the number of pin types may change in the future, I have to, within my app, pull the types, parse them into an array of custom objects, and loop through each one and add their info into the NSExpression's format. 由于引脚类型的数量将来可能会发生变化,因此我必须在我的应用程序中提取类型,将它们解析为一组自定义对象,然后遍历每个对象并将其信息添加为NSExpression的格式。 Below is an example of how I am doing that: 以下是我如何执行此操作的示例:

//Create a new style layer, like in the previous example
let icons = MGLSymbolStyleLayer(identifier: "icons", source: source)

//Create a prefix type string for our format string. We will modify 
//this based on the data in our categories 
var format = "MGL_MATCH(type, "

//Loop through the array and modify our format string to include our 
//pin type
for pinType in self.pinTypes {
    format += "'\(pinType.id ?? "")', %@, "
}

//Add the suffix to the format string
format += "%@)"

The end result of our 'format' string will always look something like this (though with a varying number of pinTypes): 我们的“格式”字符串的最终结果将始终看起来像这样(尽管pinTypes的数量不同):

MGL_MATCH(type, '0lah2lqnit8sae8', %@, 'moyxexbimf988g3', %@, 'rweisxrjjahriou', %@, 'phn9kssirq6p99f', %@, 'wgpyy6bvw0dxmfp', %@, 'knj2q61ip0xfspy', %@, 'q8e5zqkm8aj9bvl', %@, '16rxmcilhes742c', %@, 'c2srv0rkx3wtagm', %@, 'jorbix53907eikq', %@, 'L1E5cRH2mVWC5qp', %@, 'Aur0Ok57zrtxBiL', %@, 'i5261q9qjqaftfh', %@, '9ru1hhcjwqx4c51', %@, 'ebnxme3pwq6q7o3', %@, 'oyn45ntbub7upei', %@, 'hb1fy24bme5e040', %@, 'xr2pmgtged1w678', %@, '97st6t0fwb6anwz', %@, 'ovwe99ejboz7zpb', %@, 'amvm4xe85s0g6sx', %@, 'gj801lf4co3h1zm', %@, '7emo3defagedy6l', %@, '9atby0ig427fkc4', %@, '6w4asp3yxs4e6ez', %@, 'tdmmyqwtn5ncy55', %@, 'yd4epiob1mg6tc3', %@, 'icb59kmni3thlmd', %@, 'eh9mgf4lp50ar88', %@, 'lxjccng4fb7sk05', %@, '2jg3aqkltbsktof', %@, 'e0otypxpbq2syzm', %@, '25af3o1wxo77s8b', %@, '1r6z9zdi8uxtf7m', %@, 't1zxv955vw5dfep', %@, 'iq93veeuccsrqye', %@, 'osviabneknsqo2x', %@, 'u6mps2zv2ivs4n8', %@, 'r2q9u8dhhk94km4', %@, 'wp6jmyyeh17nocd', %@, '4now4xnrylx7010', %@, 'f8uy2twfr2r3m7f', %@, 'lhw9bs31nr2twlx', %@, 'qvnfna00n9wnkgu', %@, 'g8f5zc7gcei1aax', %@, 'spxlscffbf0ve9q', %@, 'dir96qh9w1n43ys', %@, 'dgrj9voh1ybhv5j', %@, 'hdwp8w1lfhcurq9', %@, 'twpx9aeb5kkkju2', %@, 'eb85y3w2zywfpet', %@, '9dd6yp6c3e4oyno', %@, 'd61qrfm60vq4mqh', %@, 'hcjxvgzr0kiqbsf', %@, 'izygh92tmdd5r07', %@, 'ymd2p3k5voo27te', %@, 'l87mls4z0zy534u', %@, 'ybr1twmjafdr1cf', %@, 'eqeio0phb1gj50y', %@, 'dn48bxo5hkt7295', %@, 'uE5z1pDR6U1pPhR', %@, '6801ek42qsn1hl2', %@, 'BWPcCGJ0bTlqYhj', %@, 'wzEaDVI28xvuENW', %@, 'yiXttIPk0oLQAc3', %@, 'b6nadw9emiband2', %@, 'yxt8w275plqxws4', %@, '99lo09p6wr8wcdv', %@, '1hhoeiony8jt0rx', %@, 'bkcmo89dcvdh7px', %@, 'nz8d748p4np9bll', %@, '6vpts6ytusz51n5', %@, %@)

So, I am able to get the format string created with dynamic data pulled from our API request, but now comes the hard part. 因此,我能够从API请求中提取使用动态数据创建的格式字符串,但现在遇到了困难的部分。 How do I pass a dynamic number of arguments into a function?! 如何将动态数量的参数传递给函数?

Note that the next step is to set the iconImageName property to an NSExpression that can take any number of arguments. 请注意,下一步是将iconImageName属性设置为可以使用任意数量参数的NSExpression。 Recall our first example with hard-coded data: 回想一下第一个使用硬编码数据的示例:

ports.iconImageName = NSExpression(format: "MGL_MATCH(type, 'redPin', %@, 'bluePin', %@, 'greenPin', %@, 'grayPin', %@, %@)", NSExpression(forConstantValue: "redMarker"), NSExpression(forConstantValue: "blueMarker"), NSExpression(forConstantValue: "greenMarker"), NSExpression(forConstantValue: "grayMarker"), defaultShape)

The first argument is the format string, all other arguments are NSExpression s that are 'populating' that format string. 第一个参数是格式字符串,所有其他参数是“填充”该格式字符串的NSExpression How can I 'loop' through the pinTypes array and create an individual NSExpression for each one and pass each individual NSExpression as an argument when setting the style layer's iconImageProperty? 在设置样式层的iconImageProperty时,如何在pinTypes数组中“循环”并为每个NSExpression创建一个单独的NSExpression并将每个单独的NSExpression作为参数传递?

TLDR Is there a way you can, when passing arguments into a function that can take any number of arguments, loop through an array of potentially varying size, create an object from each element in that array, and then pass it as an argument into the function that can take any number of arguments? TLDR有什么方法可以将参数传递到可以接受任意数量参数的函数中,循环遍历大小可能不同的数组,从该数组中的每个元素创建一个对象,然后将其作为参数传递给可以接受任意数量参数的函数?

I may be misunderstanding the question. 我可能会误解这个问题。 I don't know if you want a general way to do this, but NSExpression has an init that takes an array: https://developer.apple.com/documentation/foundation/nsexpression/1413484-init 我不知道您是否需要通用方法来执行此操作,但是NSExpression有一个采用数组的init: https : //developer.apple.com/documentation/foundation/nsexpression/1413484-init

So you could do something like: 因此,您可以执行以下操作:

let defaultShapeExpression = NSExpression(forConstantValue: "grayMarker")
// Either do clean array or add your initial arguments
var expressionArguments = [Any]()
var format = "MGL_MATCH(type, "

for pinType in self.pinTypes {
    format += "'\(pinType.id ?? "")', %@, "
    expressionArguments.append(NSExpression(pinType.iconImageProperty))
}

format += "%@)"
expressionArguments.append(defaultShapeExpression)

let expression = NSExpression(format: format, argumentArray: expressionArguments)

Hopefully this helps. 希望这会有所帮助。 I'm sitting at my desktop, so I can't really test anything myself. 我坐在桌面上,所以我自己无法真正进行任何测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM