I created a multi-platform game in Xcode and UIBezierPath gives a "Cannot find 'UIBezierPath' in scope" error. I'm sure I'm just missing importing a kit but I don't know which one.
short answer: if you're trying to use UIBezierPath you need to import UIKit
longer note re "multi-platform": your question doesn't provide much context.. but if you mean you started developing a UIBezierPath for iOS, and then switched to a different platform target (ex: macOS), then yes many of your classes won't work. often, but not always, there is simply an equivalent class for macOS that uses the "NS" prefix instead of the "UI" prefix. (NS is a legacy reference to "Next Step"). so try using AppKit classes like NSBezierPath when you target macOS, instead of UIKit classes.
#if os(macOS)
import AppKit
#elseif os(iOS)
import UIKit
#endif
warning: UI/NS classes frequently have different implementation. so it's normal to have different constructors, function calls, etc. meaning you often have to have two implementations in code using the above if/elseif/endif structure. yes this can be tedious.
UPDATE
Here is an example for drawing an ellipse in both macOS and iOS. note: the macOS version uses a CGMutablePath (since there's not a simple way to construct a SKShapeNode from an NSBezierPath on macOS like there is on iOS). if you do want to use NSBezierPath, you might also try these techniques for converting NSBezierPath to CGPath
override func didMove(to view: SKView) {
let rect = CGRect(x: 0, y: 0, width: 200, height: 200)
#if os(macOS)
let path = CGMutablePath(ellipseIn:rect, transform:nil)
let shape = SKShapeNode(path:path)
#elseif os(iOS)
let path = UIBezierPath(ovalIn: rect)
let shape = SKShapeNode(path: path.cgPath)
#endif
addChild(shape)
}
Related
I am using RealityKit face anchors. I downloaded a model from SketchFab but I am trying to put the model on the face it does not work and does not display anything.
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let configuration = ARFaceTrackingConfiguration()
arView.session.run(configuration)
let anchor = AnchorEntity(.face)
let model = try! Entity.loadModel(named: "squid-game")
anchor.addChild(model)
arView.scene.addAnchor(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) { }
}
One of the most common problems that AR developers can deal with is model size. In RealityKit, ARKit, RoomPlan & SceneKit, the working units are meters. Quite often models created in 3dsMax or Blender are imported into Xcode in centimeter scale. Therefore, they are 100 times bigger than they should be. You cannot see your model because you may be inside it and its inner surface of shader is not rendered in RealityKit. So, all you need is to scale the size of the model.
anchor.scale /= 100
The second common problem is a pivot point's location. In 99% of cases, the pivot should be inside the model. Model's pivot is like a "dart", and .face anchor is like "10 points". Unfortunately, RealityKit 2.0 does not have the ability to control the pivot. SceneKit does.
There are also hardware constraints. Run the following simple check:
if !ARFaceTrackingConfiguration.isSupported {
print("Your device isn't supported")
} else {
let config = ARFaceTrackingConfiguration()
arView.session.run(config)
}
I also recommend you open your .usdz model in Reality Composer app to make sure it can be successfully loaded and is not 100% transparent.
Check your model.
Is there any error when you run the demo?
You can use a .reality file to test, and you can also download a sample from the Apple Developer site.
I am currently looking into options on how to transform objects colour from Swift. The object has been added to the scene from Reality Composer.
I found in the documentation that I can change position, rotation, scale, however, I am unable to find a way how to change colour.
Xcode 14.2, RealityKit 2.0, Target iOS 16.2
Use the following code to change a color of a box model (found in Xcode RealityKit template):
let boxScene = try! Experience.loadBox() // Reality Composer scene
let modelEntity = boxScene.steelBox!.children[0] as! ModelEntity
var material = SimpleMaterial()
material.color = .init(tint: .green)
modelEntity.model?.materials[0] = material
arView.scene.anchors.append(boxScene)
print(boxScene)
Downcast to ModelEntity is necessary for accessing model's components:
If you need to change a transparency of your model, use the following approach.
Look into changing the material of the object.
Strikethrough is not being displayed, but underline does. The code is as below, its fairly straight forward. When I comment out the underline the text is displayed without a strikethrough, when I comment out the strikethrough and display the underline it works fine. I've tried everything — I must be missing something obvious, the docs say strikeout should work.
I'm running macOS 10.13.6 and Xcode 10.1.
import AppKit
import PlaygroundSupport
class CustomView: NSView {
override func draw(_ dirtyRect: NSRect) {
let attrString = NSAttributedString(
string: "Hello",
attributes: [
//NSAttributedString.Key.underlineStyle: NSUnderlineStyle.thick.rawValue,
NSAttributedString.Key.strikethroughStyle: NSUnderlineStyle.thick.rawValue
]
)
let line = CTLineCreateWithAttributedString(attrString)
// Set text position and draw the line into the graphics context.
let context = (NSGraphicsContext.current?.cgContext)!
context.translateBy(x: 10, y: 10)
CTLineDraw(line, context)
}
}
let customView = CustomView(frame: NSRect(x: 0, y: 0, width: 400, height: 400))
PlaygroundPage.current.liveView = customView
Playground settings. To run this in a Xcode Playground just be sure to change the platform to macOS in the inspector settings (all new playgrounds are set to iOS by default).
CoreText does not have native support for the strikethrough typographic text decoration (but supports underlines just fine as you noted in your question). The full list of string attributes supported by CoreText is described here.
This old, Objective-C based blog post provides the necessary details to implement strikethrough manually using CoreText APIs. Unfortunately, not a quick fix at all.
The higher-level TextKit framework does provide strikethrough support though. To quickly see that working just replace this line in your original code:
CTLineDraw(line, context)
with this instead:
attrString.draw(at: .zero)
And, by the way, that somehow helps validate that there was nothing wrong with your original NSAttributedString to begin with ;)
Of course, depending on how much your code relies on CoreText, switching over to TextKit might be a non-trivial task, so you need to keep that in mind as well.
I have a SpriteKit scene in a swift playground (a SKView class with all the functions that come with it such as didMove, touchesBegan and Update), and when the live view is running it always responds super slow to touches and interactions. My question is would moving the whole source code from the swift playground to a separate swift file and import it into the "Sources" folder help with the live view response, and regardless of if it helps or not, how do I do it?
Here is what my swift playground looks like:
import PlaygroundSupport
import SpriteKit
import AVFoundation
import UIKit
class GameScene: SKScene {
//my source code
}
let sceneView = SKView(frame: CGRect(x:0 , y:0, width: 720, height: 540))
if let scene = GameScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
sceneView.presentScene(scene)
}
PlaygroundSupport.PlaygroundPage.current.liveView = sceneView
I also have about ten png and a couple .mp3 in the "Resources" folder, as well as Action.sks and GameScene.sks.
Found out a little earlier that when I move the GameScene class into a separate swift file everything would render very smoothly.
I have created a new iOS SWIFT file in XCode and wish to create a very simple class which holds a SKSpriteNode. When doing this, autocomplete and coloring (as set in preferences) is not working on my variables. Sample code:
import Foundation
import SpriteKit
class dots {
var dot = SKSpriteNode(imageNamed: "funnyFace.jpg")
dot.position = CGPoint(x: 100.0, y:100.0)
addChild(dot)
}
Any help would be greatly appreciated.
You have to put the code – except the variable declaration line – into a function.
import Foundation
import SpriteKit
class Dots {
var dot = SKSpriteNode(imageNamed: "funnyFace.jpg")
func positionAndAddTheDot() {
dot.position = CGPoint(x: 100.0, y:100.0)
addChild(dot)
}
}