With an iOS playground set up as simply as this:
import UIKit
import SpriteKit
import XCPlayground
let s = CGSize(width: 300, height: 300)
let f = CGRect(origin: CGPointZero, size: s)
let view = SKView(frame: f)
let scene = SKScene(size: s)
scene.backgroundColor = SKColor.redColor()
view.presentScene(scene)
XCPShowView("main view", view)
I'm getting this in the console:
2014-09-04 17:02:13.358 SpriteKitBETA7[2009:20695] Error sending deferral props: 0x10000003
There IS a "main view" box in the Assistant Editor thing, but it doesn't display anything. This exact same code (with import Cocoa instead of import UIKit) works perfectly on an OSX playground.
I am aware I can just test stuff in an OSX playground (though it would be more convenient on an iOS one since I don't want to use Yosemite but I do have the iOS7 SDK) and copy-paste to my project, but I wanted to know if anyone understood what's happening here.
Per the Xcode 6 Release Notes, you will want to enable Run in Full Simulator in the File Inspector. Keep in mind this will run kind of slow since it is running through iOS Simulator. You'll have to wait a while for the iOS Simulator to launch before your XCPShowView starts displaying in the playground's Timeline.
In the Xcode menu bar, go to View > Utilities > Show File Inspector (⌘+⌥+1)
In the File Inspector on the right, under Playground Settings, make sure the Platform is set to iOS
Make sure Run in Full Simulator is checked.
If you mouse over the Run in Full Simulator option it explains that you should use this with views that animate or use OpenGL. Both of which apply to using either SceneKit or SpriteKit.
What did you see? I got as far as seeing a scene view with a color background I want. Try this:
import UIKit
import SceneKit
import QuartzCore
import XCPlayground
let view = SCNView(frame: CGRectMake(0, 0, 300, 300))
let myScene = SCNScene()
view.scene = myScene
view.backgroundColor = UIColor.blueColor()
view.backgroundColor = UIColor.yellowColor()
let root = view.scene?.rootNode
XCPShowView("The Scene View", view)
You can test it by diff color, and it rendered it. However, if i add a sphere to the root node, nothing happens. And I also see this in my Console Output:
2014-09-13 16:59:35.766 SceneKitPlayground[23682:13804922] Error sending deferral props: 0x10000003
Additionally, if I switch the thing to OS X, the same code that add the sphere will work.
I managed to get it running by opening the file inspector, changing the playground settings to OSX, then back to iOS and checking 'Run in Full Simulator'. This is in XCode 6.1.
Related
I am using a PDFView to display images in my app (built using SwifUI), simply for quick and easy pinch-to-zoom functionality. This worked perfectly in iOS 15, but since updating to iOS 16, the app freezes when attempting to load the image viewer (PhotoDetailView below). The issue persists across both the simulator and a physical device.
Here is the code I'm using:
import SwiftUI
import PDFKit
struct PhotoDetailView: UIViewRepresentable {
let image: UIImage
func makeUIView(context: Context) -> PDFView {
let view = PDFView()
view.document = PDFDocument()
guard let page = PDFPage(image: image) else { return view }
view.document?.insert(page, at: 0)
view.autoScales = true
return view
}
func updateUIView(_ uiView: PDFView, context: Context) {
// empty
}
}
When I run the code on iOS 16.0 in the simulator, I get 2 errors in the console:
[Assert] -[UIScrollView _clampedZoomScale:allowRubberbanding:]: Must be called with non-zero scale
[Unknown process name] CGAffineTransformInvert: singular matrix.
I have been able to isolate the issue to view.autoscales = true. If I print view.scaleFactor, I can see that it is 1.0 before the autoscale and 0.0 afterward (which is what appears to be prompting the errors). These errors also show up in the console when using iOS 15 in the simulator, but the images load as expected.
When view.autoscales = true is commented out, the image loads, albeit at a size that is much larger than the device screen.
Does anyone have any idea what may be causing this? I'd really like to avoid having to build a custom viewer, since I'm just trying to let users quickly pinch to zoom on images.
I managed to resolve this issue. I'm posting my solution here, in case anyone else runs into the same type of problem.
The issue only occurred when using a NavigationLink to navigate to PhotoDetailView. This led me to look more closely at my navigation stack.
After some digging, I found that the problem was related to my use of .navigationViewStyle(.stack) on the NavigationView. I needed this modifier to get things to display correctly on iOS 15, but the same modifier was breaking my image viewer with iOS 16.
My solution was to create a custom container to replace NavigationView, which conditionally uses NavigationStack for iOS 16, or NavigationView + .navigationViewStyle(.stack) for iOS 15. That worked like a charm and my image viewer is back in action.
I found inspiration for my custom container here: https://developer.apple.com/forums/thread/710377
since the release of the new macOS Moterey operating system (12) my MacCatalyst application does not load some views at startup until I resize the window or change focus.
If I look at XCode's Debug View Hierarchy these views are not present.
If, on the other hand, I use the classic debug (while they are not shown) it turns out that they have the correct frame (origin and size), superviews and window.
To show them I have to resize the window (manually, using the mouse) or remove the focus from the app (for example by clicking on another window and then clicking the app window again).
Only after doing one of these two things are the views loaded.
Has anyone experienced the same behavior?
The application is developed in Swift only with UIKit and various Storyboards (without SwiftUI).
Thanks a lot to everyone.
I understand what happens.
If it can be useful to anyone ...
I use custom margins for my UIViewControllers. To calculate a margin, I use the minimum width of a scene as a variable.
I take this value in this way:
var minSceneWidth:CGFloat = 400
scenes.forEach { windowScene in
if let w = windowScene.sizeRestrictions?.minimumSize.width {
if minSceneWidth > w {
minSceneWidth = w
}
}
}
Since the latest version of macOS the value "minimumSize.width" seems to be also "0" and this is not good for the calculation of my margins.
Thank you all.
I am currently handling an end-to-end SwiftUI project which involves a ClockKit complication. As one of complication's templates requires an image (UIImage) I need to render (snapshot) an existing SwiftUI View to an image. I have found a couple of possible solutions to this problem, including the following View extension:
extension View {
func snapshot() -> UIImage {
let controller = UIHostingController(rootView: self)
let view = controller.view
let targetSize = controller.view.intrinsicContentSize
view?.bounds = CGRect(origin: .zero, size: targetSize)
view?.backgroundColor = .clear
let renderer = UIGraphicsImageRenderer(size: targetSize)
return renderer.image { _ in
view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
}
}
}
The problem I have is that wherever I implement this extension I keep getting "not in scope" Xcode errors ("Cannot find 'UIHostingController' in scope", "Cannot find 'UIGraphicsImageRenderer' in scope", "Cannot infer contextual base in reference to member 'clear'").
SwiftUI and UIKit are imported in these Swift files (but I think the latter shouldn't be necessary). Xcode 12.5.
Please do share some tips that could help overcome this hurdle... I am a rather inexperienced developer and I could be missing something rather obvious, but at this point I'm pulling my hair out. Whenever I implement a reasonable solution that happened to be in other questions or websites it always comes to UIKit specific commands not being in scope.
Edit: So it turns out this extension works only if implemented in main ContentView for iOS target. Does not work if put in any other directory. However I need this extension to work in files of (watchOS) Extension files (as I said it's needed for CK Complication) and it's not possible to set target membership of the main iOS ContentView also for (watchOS) Extension, as then two ContentViews would apply to one watchOS version and error occurs. How then effectively place the above extension code so it could apply for where it's needed?
The problem for the errors pop up (like Cannot find UIHostingController in scope and others) is because UIHostingController and UIGraphicsImageRenderer are not available on watchOS, meaning the extension, as written, will not compile on that platform.
Refer to my other answered question.
When running the generated Augmented Reality app with RealityKit from Xcode, nothing appears on the screen and I'm getting weird logs on the console:
2020-09-16 16:54:29.246883+0200 TestAR[494:29654] Metal GPU Frame Capture Enabled
2020-09-16 16:54:29.247203+0200 TestAR[494:29654] Metal API Validation Enabled
2020-09-16 16:54:29.792709+0200 TestAR[494:29654] Compiler failed to build request
2020-09-16 16:54:29.792957+0200 TestAR[494:29654] [Graphics] makeRenderPipelineState failed [output of type ushort is not compatible with a MTLPixelFormatR16Float color attachement.].
2020-09-16 16:54:29.792989+0200 TestAR[494:29654] [Graphics] makeRenderPipelineState failed.
I have tried to run the app on my two devices and the result is the same. Also tried to use Xcode 12, same result. What's even more disturbing is that I got the app to work like 2 times on the 20+ tries at random without changing anything, just killing the app and restarting or closing xcode and restaring.
Here is the code, but this is just the basic generated code:
struct ContentView : View {
var body: some View {
return ARViewContainer().edgesIgnoringSafeArea(.all)
}
}
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let boxAnchor = try! Experience.loadBox()
arView.scene.anchors.append(boxAnchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
At this point I don't really understand what I'm doing wrong, here are the additionnal informations:
macOS Catalina v10.15.5
iPhone X 13.5.1
iPhone X 13.7
iPhone 6S Plus 13.5.1
Xcode 11.7
Xcode 12
At first you have to make sure that you didn't change a content in AppDelegate.swift file. A window's root view controller must come from contentView:
let contentView = ContentView()
window.rootViewController = UIHostingController(rootView: contentView)
window.makeKeyAndVisible()
Solution I
Sometimes in Xcode you may observe a bug – your app can't be launched or run due to some errors found in intermediate compiled data folder. All you need to do is to empty a DerivedData directory.
For that in Finder just press a shortcut Cmd-Shift-G and specify the following path to get to desired directory:
~/Library/Developer/Xcode/DerivedData/
After the deletion of a content of DerivedData directory your compiled app must be working as expected.
Additional info about DerivedData:
DerivedData is a folder located in ~/Library/Developer/Xcode/DerivedData by default. It’s the location where Xcode stores all kinds of intermediate build results, generated indexes, etc. DerivedData location can be configured in Xcode preferences (Locations tab).
Solution II
If the above two steps didn't help, you should reinstall Xcode.
When creating a new Swift Playground / .playgroundbook intended to be used on the iPad App, I often received the error message:
"Problem running playground. There was a problem encountered while running this playground. Check your code for mistakes."
I could track this issue down to be caused when adding certain subviews to my live view. To be more precise, my goal is to split a UIImage into multiple parts and create new UIImageViews for them:
for x in 0..<parts {
for y in 0..<parts {
//Create UIImageView with cropped image
let pieceView = UIImageView.init(frame: CGRect.init(x: CGFloat(x)*singleSize.width, y:CGFloat(y)*singleSize.height, width: singleSize.width, height: singleSize.height))
let imageRef = image.cgImage!.cropping(to: CGRect.init(x:0, y:0, width: 100, height: 100));
pieceView.image = UIImage.init(cgImage: imageRef!)
//Add them to an array
self.viewArray.append(pieceView)
}
}
And that's where things become very tricky for me: Adding 7 of these UIImageViews now works without a problem. But as soon as I want to add 8 or more of them, the playground stops working and gives the error message "Problem running playground..." (see above)
What I tested so far:
Adding UIImageViews with the same image does not cause this problem
Cropping the UIImage in a background thread and adding the view on the main thread does not help either
Creating the UIImageViews without adding them to the live-view does not cause any problems
The code works well when being executed on a mac playground, no matter how man views to add
I experienced this kind of iPad Swift Playground run-time error while adding multiple UI elements.
The problem caused by the default setting of "Enable Results" in the playground's property which is set to be ON. The "Enable Results" previews all the in-line object results' viewer. It makes the swift playground crashed when you produce many UI elements.
Try to disable the "Enable Results". It works for me.
I saw a similar issue, and the problem was that it was just a nil incorrectly used.
In order to get a clear error message, just create a playground with the same files, and run it on the mac: in this way you can get more detailed information about what is going on and find easier to solve your issue.
Let me know if you find any difficulties :)
Probably is a late answer... but I was experiencing same issue during last week... finally today just figure it out how to solve:
I was running a piece of code where I add a background view as next:
func createView(){
// gray background
let marco = CGRect(x:0, y: 0, width: 603, height: 825)
vista = UIView(frame: marco)
vista.backgroundColor = UIColor.gray
vista.isUserInteractionEnabled = true
vista.tag = 5
PlaygroundPage.current.liveView = vista
PlaygroundPage.current.needsIndefiniteExecution = true
}
But I place this at the beginning of the code
What I have changed is :
PlaygroundPage.current.liveView = vista
PlaygroundPage.current.needsIndefiniteExecution = true
Placing it at the end of all the code, before you start to run your program... if you need more detail let me know and can share more information.