Ok, I am working in Swift playgrounds here and cannot figure out how to present an SkScene that is another class. So far I have placed this SKScene file, GameScene.swift, in my Sources folder and made it public.
In my main playground file I have tried:
import PlaygroundSupport
import SpriteKit
import XCPlayground
import Foundation
let frame = CGRect(x: 0, y: 0, width: 500, height: 600) //view size
let view = SKView(frame: frame)
let scene = GameScene(fileNamed: "GameScene")
//scene.backgroundColor = NSColor.blue
view.presentScene(scene)
view.showsFPS = true;
PlaygroundPage.current.liveView = view
Along with any other answer I could find on stack overflow. Nothing is working - the playground timeline is just a blank grey and this is output:
Is this impossible?
Yes it i possible, but at the moment your Gamscene object is nil. This is because GameScene(filenamed: "" ) only works when you have the scene builder. Wish your not using in Xcode.
Instead. Use
GameScene(size: CGSize)
and make sure you create the game scene with
class GameScene : SKScene {
override sceneDidLoad() {
super.sceneDidLoad()
}
}
after that present your scene from a view
let sceneSize = CGSize(width: 250, height: 550)
let scene = GameScene(size: sceneSize)
let viewRect = CGRect(x: 0, y: 0, width: 250, height: 550)
let skView = SKView(frame: viewRect)
skView.presentScene(scene)
PlaygroundPage.current.liveView = skView
Thats an example to get you started ^^
Related
I have created two triangle shapes and I am trying to color each of them individually when I click on it. The #State variable is created inside PaintView which creates a Shape that contains a single path.
The behavior I’m seeing is that whenever I click on a shape, it re-creates both shapes, instead of only the one I’m tapping on (I can observe this based on the print that I've added to BuildShape).
Now, my understanding is that whenever a state changes, SwiftUI will re-render the entire View that contains that #State, and its child views, but since my shapes are in different views that don't relate, why is SwiftUI re-rendering both of them?
This diagram shows how the views related to each other:
For example, this is what happens when I tap on the bottom triangle:
When I tap on the bottom triangle for the first time, SwiftUI re-creates the bottom triangle twice, and the top triangle once
Path: 0 0 m 100 100 l 200 0 l
Path: 100 100 m 0 200 l 200 200 l
Path: 100 100 m 0 200 l 200 200 l
When I tap on the bottom triangle again (and for as many other times), SwiftUI re-creates the bottom triangle once, and the top triangle once
Path: 0 0 m 100 100 l 200 0 l
Path: 100 100 m 0 200 l 200 200 l
This is the code I'm using:
import SwiftUI
import UIKit
struct BuildShape: Shape {
let path: Path
func path(in rect: CGRect) -> Path {
print("Path:", path)
return path
}
}
struct PaintView: View {
let path: Path
#State var color = Color.black
var body: some View {
BuildShape(path: path)
.fill(self.color)
.onTapGesture(count: 1) {
self.color = Color.blue
}
}
}
struct DrawView: View {
var triangle1Path: Path {
var path = Path()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 100, y: 100))
path.addLine(to: CGPoint(x: 200, y: 0))
return path
}
var triangle2Path: Path {
var path = Path()
path.move(to: CGPoint(x: 100, y: 100))
path.addLine(to: CGPoint(x: 0, y: 200))
path.addLine(to: CGPoint(x: 200, y: 200))
return path
}
var body: some View {
ZStack {
PaintView(path: triangle1Path)
PaintView(path: triangle2Path)
}
}
}
The views containing triangle shapes are overlap (because they are in ZStack), and as views by default are not opaque, changing one can affects resulting appearance so redrawn all in ZStack.
ZStack {
PaintView(path: triangle1Path)
PaintView(path: triangle2Path)
}
Put them for example into VStack and you'll see that only tapped is redrawn, because rendering engine knows now that views independent.
VStack {
PaintView(path: triangle1Path)
PaintView(path: triangle2Path)
}
I have a subview from another view controller, whenever my scroll arrives on it, the subview change it's position to x = 0 and y = 0, below my navigation bar, but if I scroll fast and not stop on that view, everything is fine.
the code I use for addSubView is :
let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "saleView") as! SaleViewController
self.addChildViewController(popOverVC)
popOverVC.view.frame = CGRect(x: 0 , y: 0 , width: saleTopView.frame.width, height: saleTopView.frame.size.height)
saleTopView.addSubview(popOverVC.view)
what I miss? thanks
add
popOverVC.didMove(toParentViewController : self)
at the end. Not a must do, but for simplicity, you could also rewrite
popOverVC.view.frame = self.saleTopView.frame
I would like to add image and texts (under each image view) in ScrollView.
I add ScrollView firstly and add UIImage View. But, I add two images in image array and it only appears one image when I run the app. Here is my code;
#IBOutlet weak var imgView: UIImageView!
var imgArray = [#imageLiteral(resourceName: "home_image"),#imageLiteral(resourceName: "provider_image")]
and in ViewDidLoad() function,
for index in 0 ..< imgArray.count
{
let imgView = UIImageView()
debugPrint(index)
imgView.image = imgArray[index]
}
I also want to add each image caption under each image. How to do it? Why only one image appear? :(
Try this:
let width = customScroll.frame.size.width
for item in 1..<4{
image = UIImageView(frame: CGRect(x: (CGFloat(item) * width - width), y: 10, width: width, height: 250))
image.image = UIImage.init(named: "img"+String(item))
customScroll.addSubview(image)
print(image.frame)
}
customScroll.contentSize = CGSize(width: view.frame.size.width * 4, height: 300)
I have a simple test application and I want to pan an image inside its view. It will not pan or zoom and I can't see what's wrong with my code.
I have followed this tutorial but implemented it in code. I've made the image width the same as the height so I can pan without necessarily zooming.
Here is my code
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
return scrollView
}()
let zoomImageView: UIImageView = {
let imageView = UIImageView()
imageView.isUserInteractionEnabled = true
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
imageView.image = #imageLiteral(resourceName: "lighthouse")
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let screenSize = UIScreen.main.bounds
let screenHeight = screenSize.height
scrollView.frame = CGRect(x:0, y:0, width: screenHeight, height: screenHeight)
scrollView.delegate = self
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 3.0
zoomImageView.frame = CGRect(x:0, y:0, width: screenHeight, height: screenHeight)
scrollView.addSubview(self.zoomImageView)
view.addSubview(scrollView)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return zoomImageView
}
}
Search in your code for the term contentSize. You don't see it, do you? But the most fundamental fact about how a scroll view works is this: a scroll view without a contentSize cannot scroll (i.e. "pan" as you put it). In particular, it must have a content size larger than its own bounds size in order to be able to scroll along that axis (height or width, or both). Otherwise, there is nothing to scroll.
First post and I'll be honest, I'm pretty bad at coding. I'm working with Swift 3 for a school project and I have a question.
I'm creating multiple subviews through a for in loop through an array...
...and each created subview contains one programmatically created label, each with a different word, and a programmatically created UI Tap Gesture attached to each view...
Import UIKit
class ViewController: UIViewController, UIGestureRecongizerDelegate
{
var array = ["Each","One","Has","Its","Own","Name"]
var label = UILabel()
var DynamicView = UIView()
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
createSubView()
//end SuperView
}
func createSubview()
{
for thing in array {
var string = array[count]
count = count + 1
DynamicView = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 160))
DynamicView.center = CGPoint(x: xV,y: yV)
DynamicView.backgroundColor = UIColor.gray
self.view.addSubview(DynamicView)
label = UILabel(frame: CGRect(x: 25, y: 25, width: 100, height: 21))
label.center = CGPoint(x: 60, y: 13)
label.textAlignment = .center
label.font = UIFont(name: "Arial", size: 13)
label.text = "\(string)"
self.DynamicView.addSubview(label)
let tapGesture = UITapGestureRecognizer(target: self, action:
#selector(ViewController.tapped(recignizer:)))
DynamicView.isUserInteractionEnabled = true
DynamicView.addGestureRecognizer(tapGesture)
}
}
func tapped (recignizer:UITapGestureRecognizer){
print("\(label.text!)")
}
}
... (I'm excluding the code that separates all the views from being stacked on top of each other, so please assume that these views are spaced out, and this list of views is in a scroll view in my actual code, just not cramming that spaghetti code in here)...
...The result of the code is a layout of subViews, each with its own label that is a different word, and a tap gesture for each subView which triggers a function...
...What I want is a way to tap on each subview and find what the text in the label is. As of right now, when you tap on a view, you get what the label.text was in the last View made, so the result of print("label.text!") --> 'Name' , which makes some sense.
Is there any possible way to find the specific labels text even though they are all called "Label"?
I'm not looking to do a collection view or anything of the sort, I need something of this sort of coding to get what I need done.
Thank you to whoever helped this foolish swift student, sorry that my Swift lingo is hot garbage like my code.
Your problem is you are initializing the same DynamicView and label inside the for loop so it will overwrite and it will have last value from the array. To solved the problem you need to create separate UIView and separate UILabel in for loop. Also you need to set userInteraction of label to true because by default its false.
for thing in array {
let dynamicView = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 160))
dynamicView.center = CGPoint(x: xV,y: yV)
dynamicView.backgroundColor = UIColor.gray
self.view.addSubview(dynamicView)
let label = UILabel(frame: CGRect(x: 25, y: 25, width: 100, height: 21))
label.center = CGPoint(x: 60, y: 13)
label.textAlignment = .center
label.font = UIFont(name: "Arial", size: 13)
label.text = thing
self.dynamicView.addSubview(label)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tapped(recignizer:)))
label.isUserInteractionEnabled = true
label.addGestureRecognizer(tapGesture)
}
Now your all view’s origin is CGPoint.zero so only last view label will visible and when you tap on label to get text of its you can get this way.
func tapped(recignizer:UITapGestureRecognizer){
if let tappedLabel = recignizer.view as? UILabel {
print("\(tappedLabel.text)”)
}
}