Swift Playground Protocol Crashing after Fixed Number of Iterations - ios

For this year's WWDC scholarship, the format required is a Swift playground. I'm building my playground in an app, where I have sliders in UITableViewCells connected to a SCNScene and SCNNode and SCNParticleSystem via a custom delegate. It works perfectly fine running as an app, running on the Mac, but when it comes to the running it in swift playgrounds on the iPad, the delegate method crashes after a constant number of iterations. I have determined it is not the method in the node itself, as I made this print("Hello") and it still crashed with the exact same 96 iterations. The node has been in both Source files and the main playground file. Any ideas or help would be greatly appreciated.
Delegate
protocol ReturnParameterDelegate {
func parameter1(value: Float)
func parameter2(value: Float)
func defaultParameter(value: Float)
}
Table View Cell
#objc private func returnValue() {
guard let delegate = delegate else { return }
print(self.parameter.title)
switch self.parameter.title {
case ParameterNames.parameter1:
delegate.parameter1(value: self.slider.value)
...
}
}
Scene
public func parameter1(value: Float) {
node.changeValue(value: value)
}
...

After many hours of work and trying this with other methods, I have found a simple solution: move code from the main .playground to separate .swift files in the Sources folder. While this shouldn't change anything, adding it to the sources made all of my methods work perfectly. This does complicate protocols and I replaced them with creating a global object instead, however. It does remove the crash after a constant number of iterations and it makes certain other functions work that were not previously (for example, changing the diffuse of a SCNNode).

I move everything to source file. And it works a little bit better.

Related

Crash when instantiating ARSCNView for the second time

I have a problem in my iPhone app when trying to instantiate an ARSCNView again, after destroying it.
In my ViewController I programmatically create an ARSCNView for motion capture interaction:
func addARSceneView() {
arSceneView = ARSCNView(frame: self.view.frame)
arSceneView.loops = true
arSceneView.session.delegate = self
self.view.addSubview(arSceneView)
arSceneView.session.run(ARBodyTrackingConfiguration())
}
When the user leaves this part of the app, I tear it down like this:
func removeARSceneView() {
arSceneView.session.pause()
arSceneView.pause(self)
arSceneView.session.delegate = nil
arSceneView.removeFromSuperview()
arSceneView = nil
}
Later, when I try to instantiate an ARSCNView for the second time using the first function above, it crashes with an EXC_BAD_ACCESS in the constructor:
I also tried to use a view from a xib which contains an ARSCNView but the same problem occurs, in that case in the init(coder) function of that view.
I found nothing on this problem, I guess usually developers only create an ARSCNView once.
TLDR: Turn "Metal API Validation" on in your scheme.
I found the culprit, after creating a sample project with only the ARSCNView, which did not have this problem. I started by stripping everything away from my original project until it was as barebones as the sample. That did not solve it, so I compared every little setting of the two, and behold: in the "Run" scheme of the original project, under "Diagnostics", I had "Metal – API Validation" ticked off. I don't remember when and why I did that; I assume it was some attempt to improve performance at one point. However, enabling this checkbox solved the problem completely.

PlaygroundBook liveView display a SceneView error

I am currently playing with PlaygroundBook. From the Doc, it says that you can use LiveView.swift to present a always-on View in the liveView. So I create a SceneViewController in the Source Folder. In the SceneViewController, I create a Sphere which lightingModel is physicallyBased, and I using a 3D map as the background contents.
Then in the LiveView.swift
import PlaygroundSupport
let page = PlaygroundPage.current
page.current.liveView = SceneViewController()
But when I run it in the iPad Air Playground. I get no error, but the liveView didn't show anything!
I spend many years finding errors. And I have try to create a new iOS Project using the same SceneViewController, and it work very well. I got no idea.
In the last, I try to change the lightingModel to .phong, and change the background to the white color.
Then the magic thing happened! The liveView now show a black sphere and the white background.
Why?
From the WWDC Session, I learn that I can use proxy to communicate with main process in Contents.swift and LiveView process.
So next, I make a extension.
extension SceneViewController: PlaygroundLiveViewMessageHandler {
public func receive(_ message: PlaygroundValue) {
if case let .string(_) = message {
changeColor()
}
}
}
And inside the Contents.swift, I create a new function
func addSky() {
if let proxy = page.liveView as? PlaygroundRemoteLiveViewProxy {
proxy.send(.string("addSky"))
}
}
And everyTime I call it, The liveView changed, see the image below. It's the same as The first time I try to use a 3D map as the background.
Does anyone know what does it happened ?

Object hierarchy is causing a memory leak in Swift

Ive been able to distill a problem seen in an app I've written, and have reproduced it in a simple example.
Given these classes:
class Thing {
var name:String = ""
var price:Double = 0.0
var changed:Double = 0.0
var percentChanged:Double = 0.0
}
class TestUIViewController: UIViewController {
}
class ViewController: TestUIViewController {
var thing:Thing?
#IBAction func clicked(_ sender: AnyObject) {
self.thing = Thing()
}
}
I created a UIView with a button, that when pressed, a thing is instantiated. With the Instruments profiler up, I can see memory leaks occurring.
However, if the ViewController class extends from UIViewController, there are no issues.
This was all reproduced from a quick test app, so there are no other external forces at play here that i can think of.
Here is the example code - https://www.dropbox.com/s/ooqh77lhpzbvpv1/ArcTest.zip?dl=0
You may have found a bug in the leak detector, and it could be quite an interesting bug, so you should report it to Apple. But there is in fact no leak. I downloaded and ran your project under Instruments and clicked the button 10 times. This is what I saw in Instruments allocations template:
That is the expected result. There are 9 transient Things, and only one persistent Thing — the one currently assigned to the property. A leak would be if there were more than one persistent Thing, and there isn't.
Also, this is what the memory gauge looks like in Xcode:
We get a little rise (a kind of "mesa") when I repeatedly tap the button, but then we settle back down to the base level again.

Rendering UIView in Swift with #IBDesignable, crash

I have a graph built in Paintcode that I am showing in a UIView. It works fine in the App but will not render in storyboard. I have read a host of different posts about overriding init frame, and init coder. However, I can't find a specific example that helps me with my problem, by showing the practical use of these overrides.
The graph takes 14 variables to produce a bar chart. Here is the class code
import UIKit
#IBDesignable
class graphRisk: UIView {
override func drawRect(rect: CGRect) {
StyleKitGraph.drawRiskGraph(ehsScale: ehsScale, ciScale: ciScale, stratScale: stratScale, qaScale: qaScale, delScale: delScale, leadScale: leadScale, peopScale: peopScale, hrmScale: hrmScale, pmScale: pmScale, costScale: costScale, finScale: finScale, assScale: assScale, itsScale: itsScale, engScale: engScale)
}
}
It looks good in the App, and it is no big deal if it doesn't render as the variables are coded, and the design is fine, however, I removed the #IBDesignable tag and it still errors the same.
Finally, how do I get the UIView to update when I enter the view controller it resided in?
So the questions are;
1 How do I get render to work for this code example?
2 Is there a way to not render the view, and stop the error that way?
3 Do I need to worry about the error as the App runs fine?
4 How do I get the UIView to refresh. What is the syntax for .setNeedsDisplay() etc? I tried lots of things and none updated or reloaded or refreshed.
As always I truly welcome all help, and thank you.
Not sure what version of Xcode you are using. I am using Xcode 6.4.
I, like you, have researched for days on many websites and tried many solutions. None of them worked. At last, I removed the #IBDesignable to my custom UI class. Not only did the error went away, the instance of the custom UI class previewed fine in Main.storyboard.
Perhaps, in the new development of Xcode, #IBDesignable is no longer necessary.

Issues with Today Widget extension

I have a Today Widget for my app, however I have been told about an issue with it.
Basically, what seems to be happening (I can't test this for myself) is that the widget will sometimes just display 'unable to load' and other times it will just display with a height of 0.
I can't really see why this is happening. I've tested it out on my device and the simulator for weeks now and have never ran into this issue.
I was wondering if it could possibly be down to the refresh code:
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
// Perform any setup necessary in order to update the view.
var defaults = NSUserDefaults(suiteName: "group.AffordIt")
var newCheck = defaults.boolForKey("new")
if newCheck == true {
completionHandler(NCUpdateResult.NewData)
} else {
completionHandler(NCUpdateResult.NoData)
}
}
'newCheck' is true whenever something changes within my app that needs to be displayed in the widget.
Does anyone know what the possible causes of these issues are?
"unable to load" message appears if your extension crashes often. You can try to re-enable it by removing and adding the extension again.
Are you using your own view controller and xib instead of using storyboard? If yes, it is probably that you didn't set the preferredContentSize in your view controller.
try to put the following code in the init function of ur view controller:
self.preferredContentSize = CGSizeMake(320, 100);
I have just began the extension programming today so I am not sure is it really helpful for u or not. Here is the result in my own widget:
Press Edit button in today extensions
Remove your extension
Add your extension again.

Resources