Loading Entities from a file - swift

I created a .reality file which i exported from Reality Composer and added to the project.
The code:
class ViewController: UIViewController {
#IBOutlet var arView: ARView!
override func viewDidLoad() {
super.viewDidLoad()
if let anchor = try? Entity.loadAnchor(named: "ARAnchorTestFile") {
arView.scene.addAnchor(anchor)
}
}
}
On devices with iOS version 13.5 or higher the app crash when the anchoring is triggered and the 3D model should be displayed.
The error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x40)
The entire project has been uploaded to this repo: https://github.com/evjand/ARAnchorTest
UPDATE: After filing a bug repport to Apple it seems like they have fixed it in the iOS 14 beta.

Seems there's a bug when reading .reality file. Use .rcproject format instead. It works.
if let anchor = try? Entity.loadAnchor(named: "AR") {
arView.scene.addAnchor(anchor)
print(anchor)
}

Related

UIDocumentPickerViewController is not working when testing with my iPad but fine with simulators

I am creating an app to display a PDF file selected by UIDocumentPickerViewController for iPads.
Although the following code works fine with simulators of Xcode, for some reason, it won't work with my test iPad (iPad Mini, 5th gen). I can select a file, and its URL seems to be obtained appropriately; however, the PDF file is not displayed.
I would appreciate it if you could help me figure out what is happening and how to fix this.
import UIKit
import PDFKit
class ViewController: UIViewController, UIGestureRecognizerDelegate, UIDocumentPickerDelegate {
#IBOutlet weak var pdfView: PDFView!
override func viewDidAppear(_ animated: Bool) {
//document picker
let documentPicker = UIDocumentPickerViewController(documentTypes: ["com.adobe.pdf"], in: .import)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = false
present(documentPicker, animated: true, completion: nil)
}
internal func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print(url)
if let pdfDocument = PDFDocument(url: url)
{
pdfView.autoScales = true
pdfView.document = pdfDocument
pdfView.displayDirection = .horizontal
pdfView.usePageViewController(true, withViewOptions: [UIPageViewController.OptionsKey.interPageSpacing: 20])
} else{
print ("error, which is what I am seeing in my iPad now")
}
}
override func viewDidLoad(){
super.viewDidLoad()
}
details of the environment:
iPad mini: 5th gen, iOS 14
Xcode: 14
Simulators: iOS 14 (I tried the
majority of simulators and the app works well with them all)
For me, in my case, it was a security issue. Adding this simple code resolved the issue:
let shouldStopAccessing = pickedFolderURL.startAccessingSecurityScopedResource()
defer {
if shouldStopAccessing {
pickedFolderURL.stopAccessingSecurityScopedResource()
}
}
I got this code from here: StackOverflow Post
You are neglecting the fact that the url is security scoped. See the documentation in the section called "Working with External Documents".
(Also note that in iOS 14 your initializer is deprecated. But that's another matter.)

What is wrong with my custom camera view?

I followed this video: https://www.youtube.com/watch?v=7TqXrMnfJy8&t=45s to the T. But when I open the camera view all I see is the black screen and white button. I get no error messages when I try I load the camera view. Can someone please assist me with what I'm doing wrong?
My code is below:
import UIKit
import AVFoundation
class CameraViewController: UIViewController {
var captureSession = AVCaptureSession()
var backCamera: AVCaptureDevice?
var currentCamera: AVCaptureDevice?
var photoOutput: AVCapturePhotoOutput?
var cameraPreviewLayer: AVCaptureVideoPreviewLayer?
override func viewDidLoad() {
super.viewDidLoad()
setupCaptureSession()
setupDevice()
setupInputOutput()
setupPreviewLayer()
startRunningCaptureSession()
}
func setupCaptureSession(){
captureSession.sessionPreset = AVCaptureSession.Preset.photo
}
func setupDevice(){
let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)
let devices = deviceDiscoverySession.devices
for device in devices{
if device.position == AVCaptureDevice.Position.back {
backCamera = device
}
}
currentCamera = backCamera
}
func setupInputOutput(){
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: currentCamera!)
captureSession.addInput(captureDeviceInput)
photoOutput?.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format:[AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil)
} catch {
print(error)
}
}
func setupPreviewLayer(){
cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
cameraPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
cameraPreviewLayer?.frame = self.view.frame
self.view.layer.insertSublayer(cameraPreviewLayer!, at: 1)
}
func startRunningCaptureSession(){
captureSession.startRunning()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated
}
}
I ran your code and it worked perfectly fine — almost! The only problem is that I had to add a Privacy — Camera Usage Description entry to the app's Info.plist. Otherwise the app crashes.
Once I did that and ran your code, I saw the live camera view on my device.
So why isn't it working for you? Let's think of some possible reasons. You didn't give enough info to know for sure (seeing as the code itself works just fine), but here are some possibilities:
You don't have the Privacy — Camera Usage Description entry in the app's Info.plist.
You are testing on the Simulator. Maybe this code works only on a device.
There is something in your interface in front of the sublayer that you add when you say insertSublayer. To test this, try saying addSublayer instead; this will make the camera layer the frontmost layer (this is just for testing purposes, remember).
Maybe your code never runs at all? Perhaps we never actually go to this view controller. To test that theory, put a print statement in your viewDidLoad and see if it actually prints to the console.
Maybe your code runs too soon? To test that theory, move all those calls out of viewDidLoad and into something later, such as viewDidAppear. Remember, this is just for testing purposes.
Hopefully one of those will help you figure out what the problem is.

How to embed and stream a video from the web within an Xcode macOS Cocoa Application?

I am trying to get my macOS Cocoa Application Xcode project to play some video when I feed it a specified URL.
To simplify the question lets just use an empty Xcode project.
I want to achieve the same level of control as I am able to get using AVPlayerViewController() in my iOS Single View Application. Within that app I am currently using the solution offered here.
However, only the second example works in my macOS Cocoa Application when adapted like so:
import Cocoa
import AVFoundation
import AVKit
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer?.addSublayer(playerLayer)
player.play()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
This option however has 2 downsides:
It creates a repetitive error message in the console:
2017-06-27 18:22:06.833441+0200 testVideoOnmacOS[24456:1216773] initWithSessionInfo: XPC connection interrupted
2017-06-27 18:22:06.834830+0200 testVideoOnmacOS[24456:1216773] startConfigurationWithCompletionHandler: Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.rtcreportingd" UserInfo={NSDebugDescription=connection to service named com.apple.rtcreportingd}
This AVPlayer solution does not offer the same control as the AVPlayerViewController() solution.
So I attempted to get the following AVPlayerViewController() solution to work. But it fails:
import Cocoa
import AVFoundation
import AVKit
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
The error I am getting is:
Use of unresolved identifier 'AVPlayerViewController' - Did you mean
'AVPlayerViewControlsStyle'?
I have tried to work around this in many different ways. It will be confusing if I spell them all out. My prominent problem seems to be that the vast majority of online examples are iOS based.
Thus, the main question:
How would I be able to successfully use AVPlayerViewController within my Xcode macOS Cocoa Application?
Yes, got it working!
Thnx to ninjaproger's comment.
This seems to work in order to get a video from the web playing / streaming on a macOS Cocoa Application in Xcode.
First, create a AVKitPlayerView on your storyboard and link it as an IBOutlet to your NSViewController.
Then, simply apply this code:
import Cocoa
import AVFoundation
import AVKit
class ViewController: NSViewController {
#IBOutlet var videoView: AVPlayerView!
override func viewDidLoad() {
super.viewDidLoad()
let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
let player = AVPlayer(url: videoURL!)
let playerViewController = videoView
playerViewController?.player = player
playerViewController?.player!.play()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
Update august 2021
Ok, it's been a while since this answer has been up and I am no longer invested in it. But it seems others still end up here and the solution needs a bit more work to work properly at times.
With thanks to #SouthernYankee65:
What is needed sometimes is to go to the project file and on the Signing & Capabilities tab check Outgoing Connection (Client). Then in the info.plist add App Transport Security Settings dictionary property, then add Allows Arbitrary Loads boolean property and set it to YES.
The video now plays. However, some errors in the console might occur.

EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0) error for a URL webview in xcode and swift

I am new to xcode and Swift and I am getting an error
EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
I've tried searching similar questions on stackoverflow and I saw that people's responses were that it's because the url is not valid, so it's returning nil. However, I am using https://google.com and I am still getting the same error. This is all my code so far. I am only trying to load a single webpage into the view controller.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = URL(string: "https://www.google.com")
myWebView.loadRequest(URLRequest(url: url!))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
After looking at various documentations and videos on the errors I found that the issue was that I was writing my code in the wrong file for the viewController as the viewController that I was targeting was a second one that I created to be access from the original one. Therefore, for anyone else who is completely new development and to xcode and swift. The original viewController.swift file is only for the first viewController. A new viewController.swift file must be created to add code to any subsequently created viewControllers.
Looks like your outlet is not connected properly and also always try to avoid doing force unwrapped. In order to prevent your crash you can use below check:-
guard let url = URL(string: "https://www.google.com") else { return }
myWebView.loadRequest(URLRequest(url: url))
or
if let url = URL(string: "https://www.google.com") {
myWebView.loadRequest(URLRequest(url: url))
}

Metal Framework not recognized

I'm currently following this tutorial on Metal/MetalKit. I have not developed for OSX before, so this is a bit new to me.
A pretty banal problem, that I'm having right from the start is, that Xcode (7.2) does not recognize, that Metal is imported. Or in a way it does, but doesn't allow me to use it's contents.
This is the content of my ViewController.swift:
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var label: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
if let device = MTLCreateSystemDefaultDevice() {
label.stringValue = "Your GPU name is:\n\(device.name!)"
} else {
label.stringValue = "Your GPU does not support Metal!"
}
}
}
I get the following error though:
When I try to import Metal explicitly, Xcode tells me that it's already implicitly imported with Cocoa.
My Deployment Target is OSX 10.11:
Why is this not working?