Fixing bugs in a github project SwiftChart - ios

I'm trying to track down the errors in this github project.
https://github.com/gpbl/SwiftChart
The owner doesn't seem to answer any questions or respond.
I can't get this example to run:
// Create a new series specifying x and y values
let data = [(x: 0, y: 0), (x: 0.5, y: 3.1), (x: 1.2, y: 2), (x: 2.1, y: -4.2), (x: 2.6, y: 1.1)]
let series = new ChartSeries(data)
chart.addSerie(series)
Xcode gives this error in regards to the data
ViewController.swift:41:31: '(Double, Double)' is not identical to 'Float'
in the main file Chart.swift, there is this section of code
var labels: [Float]
if xLabels == nil {
// Use labels from the first series
labels = series[0].data.map( { (point: ChartPoint) -> Float in
return point.x } )
}
else {
labels = xLabels!
}
I'm not quite sure how to deal with the map .

There are typos in the realm. It should read
let data = [(x: 0, y: 0), (x: 0.5, y: 3.1), (x: 1.2, y: 2), (x: 2.1, y: -4.2), (x: 2.6, y: 1.1)]
let series = ChartSeries(data)
chart.addSeries(series)
That being said, Swift by default infers 0.5 to be a Double, and his default init is looking for x and y to be of type Float.
I forked the repository, and added an init that will convert the doubles to float. This could obviously cause an issue if the double is too big, but for the small numbers it likely won't be an issue. I also added the example in question to the actual project. My fork is here.
I'll send a pull request if the owner wants to accept the changes. Otherwise, if I have time I may refactor it to all be Double and get rid of the extra init.
I added the following init in ChartSeries.swift, this prevents you from always having to define your array as it convert the array of Double value tuples to Floats.
init(data: Array<(x: Double, y: Double)>) {
self.data = data.map ({ (Float($0.x), Float($0.y))})
}

Related

Need starting and ending position of MeshResource/Box in RealityKit

let material = SimpleMaterial.init(color: .red,roughness: 1,isMetallic: false)
let doorBox = MeshResource.generateBox(width: 0.02,height: 1, depth: 0.5)
let doorEntity = ModelEntity(mesh: doorBox, materials: [material])
let anchor = ARAnchorEntity()
anchor.addChild(doorEntity)
In RealityKit, I am having box which is MeshResource, Box looks like a line. I have added this box in ARView, and have set realtime camera position. In one scenario I want to know Box/Line’s starting and ending position.
Lets say box with entity has middle/current position (0.1,0.23,-1.3) then what will be box’s left and right position ? Anchor with box is keep changing it's position with camera movement.
Thanks in advance.
Check explanation with the image
You can use this extension.
extension Entity {
func getDistancedPosition(x: Float, y: Float, z: Float) -> SIMD3<Float> {
let referenceNodeTransform = transform.matrix
var translationMatrix = matrix_identity_float4x4
translationMatrix.columns.3.x = x
translationMatrix.columns.3.y = y
translationMatrix.columns.3.z = z
let updatedTransform = matrix_multiply(referenceNodeTransform,
translationMatrix)
return .init(updatedTransform.columns.3.x,
updatedTransform.columns.3.y,
updatedTransform.columns.3.z)
}
}
To get left and right for your box, Use below code:
let side1Position = door.getDistancedPosition(x: 0, y: 0, z: self.viewModel.doorDepth/2)
let side2Position = door.getDistancedPosition(x: 0, y: 0, z: -(self.viewModel.doorDepth/2))
To make the box look like the line you must have used depth. If not then you can change the parameter accordingly. e.g. door.getDistancedPosition(x: -0.1, y: 0, z: 0)
You can also refer to this question and its accepted answer:
Position a SceneKit object in front of SCNCamera's current orientation

Regular Expression to replace CGRectMake

As CGRectMake is not available in swift 3.0 and migrator did not convert it i need to manually replace it and it is used more than 300 times in my code so can anyone help me in this to develop regular expression so i can find and replace code. What i want to do is to convert
CGRectMake(a,a,a,a) here a is some value.
to
CGRect(x: a, y: a, w: a, h: a)
Find by this:
CGRectMake\(([^,]*),([^,]*),([^,]*),([^,]*)\)
and Replace by this:
CGRect\(x:\1, y:\2, w:\3, h:\4\)
Tried it in notepad++
EDIT - With Regex:
CGRectMake\(([^,]*),([^,]*),([^,]*),([a-z|0-9|.|A-Z]*)\)
and replace with
CGRect\(x:\1, y:\2, width:\3, height:\4\)
Using regex we can not get the value of x,y,width,height dynamically.
So Alternative solution to above is,
Replace all the CGRectMake( with
appdelegateobject.CGRectMakeWrapper("
At the end add " only.
Means in your case you will replace CGRectMake(a,a,a,a) to appdelegateobject.CGRectMakeWrapper("a,a,a,a"
where appdelegateobject is the appdelegate shared instance object where you will define CGRectMakeWrapper function having string parameter as shown below :
func CGRectMakeWrapper(str: String) -> CGRect {
var rect = CGRectZero
if(str.characters.count > 0)
{
var arr = str.componentsSeparatedByString(",")
if(arr.count == 4)
{
rect = CGRect(x: CGFloat((arr[0] as NSString).doubleValue), y: CGFloat((arr[1] as NSString).doubleValue), width: CGFloat((arr[2] as NSString).doubleValue), height: CGFloat((arr[3] as NSString).doubleValue))
}
}
return rect
}
var rect = "10.0,10.0,100,100" //String
var rect1 = CGRectMakeWrapper(rect) //CGRect
I have shown sample string as rect and passed to CGRectMakeWrapper function which will return a rect. You can define this CGRectMakeWrapper function in common class which is accessible to all classes(e.g Appdelegate file).
I have one different way to solve this problem.
Step 1
In the following line
CGRectMake(a,a,a,a)
Just replace CGRectMake with CGRectMakeCustom so all will look like
CGRectMakeCustom(a,a,a,a)
Step 2
Create new Global function in the project
as follows
func CGRectMakeCustom(x: Double, y: Double, width: Double, height: Double) -> CGRect
{
return CGRect(x: x, y: y, width: width, height: height)
}
In this way it will be easy for you to start woking on Swift3
You can change mode to regular expression while searching and search for:
CGRectMake\(([^,]*),([^,]*),([^,]*),([^,]*)\)
which should be replaced by
CGRect\(x:\1, y:\2, w:\3, h:\4\)

How to tap on a specific point using Xcode UITests

I want to use Xcode UI tests with the Fastlane Snapshot to make screenshots of the Cordova app. Basically, as my entire app is just a web view, all the Xcode UI test helper methods become irrelevant, and I just want to tap on specific points, e.g. tap(x: 10, y: 10) should produce a tap at the point {10px; 10px}.
That's probably very simple, but I can't figure out how to do it.
Thanks.
You can tap a specific point with the XCUICoordinate API. Unfortunately you can't just say "tap 10,10" referencing a pixel coordinate. You will need to create the coordinate with a relative offset to an actual view.
We can use the mentioned web view to interact with the relative coordinate.
let app = XCUIApplication()
let webView = app.webViews.element
let coordinate = webView.coordinateWithNormalizedOffset(CGVector(dx: 10, dy: 10))
coordinate.tap()
Side note, but have you tried interacting with the web view directly? I've had a lot of success using app.links["Link title"].tap() or app.staticTexts["A different link title"].tap(). Here's a demo app I put together demonstrating interacting with a web view.
Update: As Michal W. pointed out in the comments, you can now tap a coordinate directly, without worrying about normalizing the offset.
let normalized = webView.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
let coordinate = normalized.withOffset(CGVector(dx: 10, dy: 10))
coordinate.tap()
Notice that I pass 0,0 to the normalized vector and then the actual point, 10,10, to the second call.
#joe To go a little further off of Joe Masilotti's approach I put mine in an extensionand gave prepositional phrases to the global and local params.
func tapCoordinate(at xCoordinate: Double, and yCoordinate: Double) {
let normalized = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
let coordinate = normalized.withOffset(CGVector(dx: xCoordinate, dy: yCoordinate))
coordinate.tap()
}
By giving the global an identifiable name I can easily understand the instance for example:
tapCoordinate(at x: 100, and y: 200)
I found Laser's answer to work fine with Xcode 11, but made a few tweaks to easily integrate it into my testing.
extension XCUIApplication {
func tapCoordinate(at point: CGPoint) {
let normalized = coordinate(withNormalizedOffset: .zero)
let offset = CGVector(dx: point.x, dy: point.y)
let coordinate = normalized.withOffset(offset)
coordinate.tap()
}
}
Now, when I need to tap on a given location, I just provide a CGPoint and call this against my XCUIApplication like so:
let point = CGPoint(x: xCoord, y: yCoord)
app.tapCoordinate(at: point)
<something>.coordinate(withNormalizedOffset: CGVector.zero).withOffset(CGVector(dx:10,dy:60)).tap()
Pass .zero to the normalized vector and then the actual point (10,60)

Accessing CGRect values directly vs normalizing them in Swift - Objective-C rules still valid?

This question is inspired by Andrew Carter's comment on a previous question about the new CGSize initializer in Swift.
The Apple Docs for CGGeometry say:
... your applications
should avoid directly reading and writing the data stored in the
CGRect data structure. Instead, use the functions described here to
manipulate rectangles and to retrieve their characteristics.
Is Apple's recommendation to not directly access the data in a CGRect still valid with Swift? Why should CGRectGetMidX, CGRectGetWidth, etc. be used in place of accessing the values of a CGRect struct directly, when these properties are now exposed with Swift's new extension on CGRect?
Consider a non-standard CGRect with a negative width and height:
var rect = CGRect(x: 0.0, y: 0.0, width: -10.0, height: -10.0)
This is a valid rectangle according to the Apple docs, as "a rectangle with an origin of [0.0, 0.0] and a size of [10.0, 10.0] is exactly equivalent to a rectangle with an origin of [10.0, 10.0] and a size of [-10.0, -10.0]."
You can standardize this CGRect by calling the legacy inline CGRectStandardize method like in Objective-C, or any of the new methods provided on the Swift extension of CGRect:
CGRectStandardize(rect) // {x -10 y -10 w 10 h 10}
rect.standardized // {x -10 y -10 w 10 h 10}
rect.standardizeInPlace() // {x -10 y -10 w 10 h 10}
But wait! This will reposition your rect on the coordinate plane, not only making your width and height positive, but making your origin negative to reflect the initial position of the rect with its negative width and height.
The inline CGRectGet functions provide an interface to normalize a specific value of your rect, without changing its origin. Swift provides an extension on CGRect so you can access the normalized values directly, rather than using the legacy C methods provided by CGGeometry:
var rect = CGRect(x: 0.0, y: 0.0, width: -10.0, height: -10.0)
rect.size.width // non-normalized, returns -10
CGRectGetWidth(rect) // bridged C function, normalized, returns 10
rect.width // new from Swift extension on CGRect, normalized, returns 10
The new interfaces:
extension CGRect {
// ...
public var width: CGFloat { get }
public var height: CGFloat { get }
public var minX: CGFloat { get }
public var midX: CGFloat { get }
public var maxX: CGFloat { get }
public var minY: CGFloat { get }
public var midY: CGFloat { get }
public var maxY: CGFloat { get }
// ...
}
So the answer is yes, the same rules for CGRect in Objective-C apply in Swift as well. The only difference here is that Swift provides an extension on some CGGeometry structs which allow you to move away from the old inline C functions bridged from the CGGeometry headers.
In Swift 3, it looks like CGRectGetWidth() is replaced by CGRect.width.

Understanding mutating functions with the self property

I'm working through Apple's Swift Programming Language book and came across the following example. I want to make sure I have the concept correct before continuing.
struct Point {
var x = 0.0, y = 0.0
mutating func moveByX(deltaX: Double, deltaY: Double) {
self = Point(x: x + deltaX, y: y + deltaY)
}
}
The book states "the moveByX function creates a brand new structure who's x and y values are to the target location."
So, if I do this;
var myPoint = Point(x: 1, y: 1)
myPoint.moveByX(2, deltaY: 2)
My understanding is Swift releases the myPoint struct with the values 1, 1 from memory, and it is no longer available. In its place a new one is created with the values 3, 3. Am I right?
To be precise values 1 and 1 are replaced by 3, 3. Location in memory is the same in both cases and allocated when particular instance is allocated.

Resources