Specify Z-order of lines - ios-charts

I plot an unknown number of series. For sake of explanation, assume that there are three; a, b and c.
This leads the issue with the first serie a to be "hidden" behind the other series. This is most noticeable when then each have different colors assigned. I could plot them in the reverse order (beginning with c), but then the legend would be in reverse as well.
Is there a way to specify that a should be on top of b and b on top of c?

I'm not sure what exactly chart you are using. But for example for LineChartView you can define your custom renderer as a descendant of LineChartRenderer class and override some functions e.g. drawData. In fact, you can just copy this function to your class and change only the drawing order of data sets.
class MyCustomRenderer: LineChartRenderer {
// I define my custom initializer for convenience
init(for chart: LineChartView) {
super.init(dataProvider: chart, animator: chart.chartAnimator, viewPortHandler: chart.viewPortHandler)
}
init(view: LineChartView) {
super.init(dataProvider: view, animator: view.chartAnimator, viewPortHandler: view.viewPortHandler)
}
override func drawData(context: CGContext)
{
guard let lineData = dataProvider?.lineData else { return }
// Here you can change the drawing order !
for i in 0 ..< lineData.dataSetCount
{
guard let set = lineData.getDataSetByIndex(i) else { continue }
if set.isVisible
{
if !(set is ILineChartDataSet)
{
fatalError("Datasets for LineChartRenderer must conform to ILineChartDataSet")
}
drawDataSet(context: context, dataSet: set as! ILineChartDataSet)
}
}
}
}
And setup you render for your chart using renderer property.
myLineChartView.renderer = MyCustomRenderer(for: myLineChartView)

Related

How can several related struct types share an init(...) method without defining read-only properties with var?

I find myself very often forced to use var properties in Swift even when properties will only be assigned once.
Here's an example: The only way I have found to have several types share an init(...) is to put the init(...) in a protocol extension. However if I do this, the properties of the struct must be assigned a dummy value before the body of the init(...) in the protocol extension is run, when it will get its "real" value.
The example below runs without error. How can color be a let property but still be assigned in Piece's init(...)?
protocol Piece {
var color: Character {set get} // "w" or "b"
init()
}
extension Piece {
init(color c: Character) {
self.init()
color = c
// Some complex logic here all Pieces share
}
}
struct Knight: Piece {
var color: Character = "_" // annoying dummy value
internal init(){}
}
// ... the other Piece types here ...
let knight = Knight(color: "w")
To make this clearer, hopefully, this is what I would like instead: (This does not compile, because of let color in struct Knight.)
protocol Piece {
let color: Character {get} // "w" or "b"
}
extension Piece {
init(color c: Character) {
color = c
// Some complex logic here all Pieces share
}
}
struct Knight: Piece {
let color: Character
}
// ... the other Piece types here ...
let knight = Knight(color: "w")
Edit (after I have found an answer, see below): Another way to state the the subject line question: How can several struct types share initialization logic, while allowing read-only properties to be let?
2nd Edit Made clear that second code example doesn't compile.
3rd Edit Made clear which let color.
With some refactoring, you can achieve minimum code duplication. Here is my solution thinking about your scenario with a different perspective:
First, I noticed that you are taking only "w" or "b" as your color property value. Since you have only two (or let's say minimal) variations of inputs you can make color part of type definition itself by using protocol with associated types and generics, rather than having it as a property. By doing this you don't have to worry about setting property during initialization.
You can create a protocol i.e. PieceColor and create a new type for each color, i.e. Black, White and your Piece protocol can have an associated type confirming to PieceColor:
protocol PieceColor {
// color related common properties
// and methods
}
enum Black: PieceColor { // or can be struct
// color specific implementations
}
enum White: PieceColor { // or can be struct
// color specific implementations
}
protocol Piece {
associatedtype Color: PieceColor
}
This approach also provides safety guarantees as you are now restricting user input to only values your code is designed to handle, instead of adding additional validation to user inputs. Also, this helps you implementing specific relations between pieces depending on their color group, i.e. only opposite colors can kill each other etc.
Now for the main part of your question, instead of trying to customize initializer you can create a static method that initializes your piece and does some shared complex handling on it:
protocol Piece {
associatedtype Color: PieceColor
init()
static func customInit() -> Self
}
extension Piece {
static func customInit() -> Self {
let piece = Self()
// Some complex logic here all Pieces share
return piece
}
}
struct Knight<Color: PieceColor>: Piece {
// piece specific implementation
}
let wKnight = Knight<White>.customInit()
let bKnight = Knight<Black>.customInit()
Get-only protocol properties are cool because conforming types have a lot of flexibility in how they define the corresponding properties. All that's required is that the property is gettable.
So if you define your protocol with a get-only property:
protocol Piece {
var color: Character { get }
}
The conforming types can define the color property as a stored variable, a let constant, or a computed property.
Stored variable:
struct Queen: Piece {
var color: Character
}
Computed property:
struct King: Piece {
var color: Character { return "K" }
}
Let constant:
struct Knight: Piece {
let color: Character
}
Each of the above satisfies the gettable property requirement imposed by the protocol.
Regarding initialization. Recall that swift automatically creates default initializers for structs, and those initializers have parameters that correspond to each of the struct's stored properties. Swift may create an initializer for Queen and Knight that looks like this:
init(color: Character) {
self.color = color
}
So if you want color to be a let constant and you want to be able to configure it with an initializer, the above definitions for Piece and Knight are sufficient. You don't need to do any additional work.
You can instantiate a Knight like so:
let knight = Knight(color: "w")
After discovering Charles Srstka's answer to How to use protocols for stucts to emulate classes inheritance. I have built a solution. It isn't the prettiest but it does allow several struct types to share initialization logic while allowing properties that should be read-only, to be defined with let.
This works:
typealias PropertyValues = (Character) // could be more than one
protocol Piece {
var color: Character {get} // "w" or "b"
}
extension Piece {
static func prePropSetup(color c: Character) -> PropertyValues {
// logic all Pieces share, that needs to run
// BEFORE property assignment, goes here
return (c)
}
func postPropSetup(){
// logic all Pieces share, that needs to run
// AFTER property assignment, goes here
print("Example of property read access: \(color)")
}
}
struct Knight: Piece {
let color: Character
init(color c: Character){
(color) = Self.prePropSetup(color: c)
postPropSetup()
}
}
struct Bishop: Piece {
let color: Character
init(color c: Character){
(color) = Self.prePropSetup(color: c)
postPropSetup()
}
}
// ... the other Piece types continue here ...
let knight = Knight(color: "w")
let bishop = Bishop(color: "b")
Out of interest a completely alternative approach:
First we define a curry function - this one taken from https://github.com/pointfreeco/swift-prelude:
public func curry<A, B, C>(_ function: #escaping (A, B) -> C)
-> (A)
-> (B)
-> C {
return { (a: A) -> (B) -> C in
{ (b: B) -> C in
function(a, b)
}
}
}
Now let's suppose we have a piece that has a Role, which is the type of piece. Role can change because you can promote pawns. Here we'll use String for Role:
struct Piece {
let color: Character
var role: String
}
To share the init that we want white pieces and black pieces, we curry the init function:
let curryPieceInit = curry(Piece.init(color:role:))
and make two partially-applied init functions that bake in either w or b for the color:
let white = curryPieceInit("w")
let black = curryPieceInit("b")
And now we can finish the partial application by passing along the remaining argument to fully instantiate a chess piece:
let wBish = white("bishop")
let wQueen = white("queen")
let blackPawns = (1...8).map { black("pawn\($0)") }
Now make Role not a string but some custom type, an enum, encapsulating the logic representing the differences between the various chess pieces.
Make the Piece.init(color:role:) private, expose the curried versions.
No protocols needed.

Select random value from a enum

select random value from given enum
public class SwiftConfettiView: UIView {
public enum ConfettiType {
case confetti
case triangle
case star
case diamond
case image(UIImage)
}
// usage in other class
confettiView.type = .confetti
Would like to set randomly confettiView triangle, star,diamond,confetti
//This will not work
confetti.type = ConfettiType.allCases.randomElement()!
Type 'SwiftConfettiView.ConfettiType' has no member 'allCases'
//So, all all confetti to an array list and load in from there!
var confettiList = [SwiftConfettiView.ConfettiType.confetti
, SwiftConfettiView.ConfettiType.diamond
, SwiftConfettiView.ConfettiType.triangle
, SwiftConfettiView.ConfettiType.star
]
confettiView.type = confettiList.randomElement()!
It's working properly!
is this approach is correct or wrong?
Here your enum is associated type. So if case of type image you have to provide a image as parameter. I have considered a default image.
extension ConfettiType: CaseIterable {
static var allCases: [ConfettiType] {
let img: UIImage = UIImage(named: "default_image")! // change as your expectation
return [.confetti, .triangle, .star, .diamond, .image(img)]
}
}
let randomEnum = ConfettiType.allCases.randomElement()
Otherwise if your image type would be something like this image(UIImage?) then we can put nil as default value. In that case it would be more convenient.
#Alexander identified your issue in the comments: Your issue is that you need to conform to CaseIterable to get access to allCases, and that only works if your enum doesn't have associated values (because there's no way to enumerate all possible UIImages).
Your workaround is fine, and it can be made nicer by taking advantage of Swift's type inference.
You might add a randomChoice(from:) function to your enum class that lets the caller specify which items to choose from. Because of type inference, you can specify the cases without fully qualifying them (eg. .confetti and .triange is sufficient).
Here is a full example:
public class SwiftConfettiView: UIView {
public enum ConfettiType {
case confetti
case triangle
case star
case diamond
case image(UIImage)
static func randomChoice(from choices: ConfettiType...) -> ConfettiType {
return choices.randomElement()!
}
}
func test() {
for _ in 1...10 {
let choice = ConfettiType.randomChoice(from: .confetti, .triangle, .star, .diamond)
print(choice)
}
}
}
SwiftConfettiView().test()
triangle
triangle
diamond
diamond
triangle
star
confetti
confetti
star
triangle
Notes:
Alternatively, you could have randomChoice take [ConfettiType]. In that case, you need to decide how to handle an empty array (either return an optional so that you can return nil for an empty array, or provide a default value such as .confetti for that case).
return choices.randomElement() ?? .confetti
Taking an array gives you the ability to provide a default value, such as:
static func randomChoice(from choices: [ConfettiType] = [.confetti, .triangle, .star, .diamond]) -> ConfettiType {
return choices.randomElement() ?? .confetti
}
For example:
// take the default values
let choice = ConfettiType.randomChoice()
// specify specific choices
let choice = ConfettiType.randomChoice(from: [.star, .diamond])
If you always just want to choose from those 4 enum values, you could just have randomChoice take no arguments and just hard code the choice from those 4 values. In that case, randomChoice could be implemented as a computed property:
static var randomChoice: ConfettiType { return [.confetti, .triangle, .star, .diamond].randomElement()! }
and called like this:
let choice = ConfettiType.randomChoice

How to Remove an Entity form a SKScene

Components of entities can be removed with:
entity.removeComponentForClass(SpriteComponent.self);
entity.removeComponentForClass(PhysicsComponent.self);
How are Entities removed from a SKScene?
There are plenty of tutorials about removing components, but I can't find anything explicit about removing entities. Is there something like removing a node?
node.removeFromParent();
I adapted this from Apple's DemoBots which contains samples for the RenderComponent and LayerConfiguration.
Array was extended using Swift solution here >> Array extension to remove object by value
var entities = [GKEntity]()
/// Stores a reference to the root nodes for each world layer in the scene.
var layerNodes = [LayerConfiguration:SKNode]()
func addEntity(entity: GKEntity)
{
self.entities.append(entity)
for componentSystem in self.componentSystems
{
componentSystem.addComponent(foundIn: entity)
}
// If the entity has a `RenderComponent`, add its node to the scene.
if let renderNode = entity.component(ofType: RenderComponent.self)?.node
{
self.addNode(node: renderNode, toLayer: .actors)
}
}
func removeEntity(entity:GKEntity)
{
for componentSystem in self.componentSystems
{
componentSystem.removeComponent(foundIn: entity)
}
if let renderNode = entity.component(ofType: RenderComponent.self)?.node
{
renderNode.removeFromParent()
}
self.entities.remove(entity)
}
func addNode(node: SKNode, toLayer layer: LayerConfiguration)
{
//
let layerNode = self.layerNodes[layer]!
layerNode.addChild(node)
}

How to constraint generic type to another generic type in Swift?

I'd like to do something like this:
class Config<T> {
func configure(x:T)
// constraint B to be subclass of A
class func apply<A,B:A>(c:Config<A>, to:B) {
c.configure(to)
}
}
So later, for example, I can apply a Config to a UILabel:
class RedViewConfig<T:UIView> : Config<T> {
func configure(x:T) {
x.backgroundColor = .redColor();
}
}
let label = UILabel()
Config.apply(RedViewConfig(), to:label)
Or extend Config classes:
class RedLabelConfig<T:UILabel> : RedViewConfig<T> {
func configure(x:T) {
super.configure(x)
x.textColor = .redColor();
}
}
Config.apply(RedLabelConfig(), to:label)
I tried to do it, but I couldn't constraint classes. So I tried with protocols and associated types, but when subclassing I found problems (like this) when overriding the associated type.
Do you actually need the generic parameter B? If your argument to: was typed as A as well, it could be any subtype of A. Like such:
class View {}
class LabelView : View {}
class Config<T> {
func configure(x:T) { print ("Configured: \(x)") }
}
func applyConfig<A> (c:Config<A>, to:A) {
c.configure(to)
}
applyConfig(Config<View>(), to: LabelView())
Classes make this way too complicated. Inheritance is almost always a bad idea in Swift if you can possibly avoid it.
Structs, though closer, still make this a bit over-complicated and restrictive.
Really, these configurators are just functions. They take a thing and they do something to it, returning nothing. They're just T -> Void. Let's build a few of those.
func RedViewConfig(view: UIView) { view.backgroundColor = .redColor() }
func VisibleConfig(view: UIView) { view.hidden = false }
And we can use them pretty easily:
let label = UILabel()
VisibleConfig(label)
We can compose them (like super, but without the baggage) if their types are compatible:
func RedLabelConfig(label: UILabel) {
RedViewConfig(label)
label.textColor = .redColor()
}
We can pass them around in data structures, and the compiler will apply the right covariance for us:
let configs = [RedLabelConfig, VisibleConfig]
// [UILabel -> ()]
// This has correctly typed visibleConfig as taking `UILabel`,
// even though visibleConfig takes `UIView`
// And we can apply them
for config in configs { config(label) }
Now if we want other syntaxes, we can build those pretty easily too. Something more like your original:
func applyConfig<T>(f: T -> Void, to: T) {
f(to)
}
applyConfig(VisibleConfig, to: label)
or even closer to your original:
struct Config {
static func apply<T>(config: T -> Void, to: T) { config(to) }
}
Config.apply(VisibleConfig, to: label)
The point is that just using functions here makes everything very flexible without adding any of the complexity of class inheritance or even structs.

Looping through all objects/sprites in a scene

Is it possible to loop through all the objects contained in a scene when the override function "didMoveToView" is called? In context, I'm trying to check all the objects to see if one of them has the name "planet1" then make it orbit around a given point.
if you need to loop through all the nodes just use
enumerateChildNodesWithName("//*", usingBlock:
{ (node, stop) -> Void in
if node.name=="planet1" {
//make it orbit
}
})
in the name string // means search the entire node tree, not just this node's children.
* is wildcard and matches any name, you can use "xxx*" to match any name starting with xxx and the same for "*xxx" to match any name ending in xxx
EDIT: you can just do:
planet1=self.childNodeWithName("//planet1")!
Just loop through all of the parent view's subviews.
override func didMoveToView(view: SKView) {
super.didMoveToView(view)
for sibling in view.subviews {
// check sibling view
}
}
Note that at least one of the objects in the loop will be equal to self. Also note that they'll all have a type of AnyObject. So you'll have to downcast. If your view named "planet1" is a particular class though:
for sibling in view.subviews {
if let planet = sibling as? PlanetSprite {
if planet.name == "planet1" {
// do stuff
}
}
}
This might be about what you're looking for.