I am trying to set a SwiftUIView as the start screen on a Game Project.
I tried setting SceneDelegate.swift as:
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: SwiftUIView())
self.window = window
window.makeKeyAndVisible()
But when I build app, still see the standard ship.scn
Does anyone know how to change the start view for a game project, from the ship.scn to a SwiftUI View?
Thanks
It "looks" like either let windowScene is failing or Main interface is still calling your storyboard. Did you start your project with a storyboard, then attempt to remove it?
I use this code in AppDelegate... hope it helps!
let win = UIWindow()
win.frame = UIScreen.main.bounds
win.backgroundColor = UIColor.black
win.rootViewController = UINavigationController(rootViewController: MainVC())
win.makeKeyAndVisible()
window = win
return true
Related
I am making an app that started with the CEFSharp minimal example code and I am using ChromeTabs in Wpf. I have my CEFSharp diverting popup windows into tabs correctly but I am having an issue grabbing the URL of these dynamic CEFSharp windows. For some reason AddressChanged is not exposed for these dynamic windows. I have tried to make use of LoadingStateChanged to place the URL in a textbox but that creates all new issues with the threads. I have spent the past few days trying to get this to work and it is driving me crazy. This is how my new tab is created but it does not expose AddressChanged event.
int counttabs = tbControlRCI.Items.Count-1;
string popURL;
popURL = popup_request;
tbControlRCI = this.etTabCntrlRCI;
//here we should open a new tab and place a new rcibrowser in it and give it the url
RCIBrowser = new ChromiumWebBrowser(popURL);
RCIBrowser.Name = "RCIBrow_" + counttabs;
string shorturl = popURL.Substring(popURL.LastIndexOf("/"), popURL.Length - popURL.LastIndexOf("/"));
ChromeTabs.ChromeTabItem newTabItem = new ChromeTabs.ChromeTabItem
{
Header = shorturl,
Name = "RCITab_" + counttabs,
Content = RCIBrowser
};
LifespanHandler lifeRCI = new LifespanHandler();
RCIBrowser.LifeSpanHandler = lifeRCI;
lifeRCI.popup_request += life_popup_request;
tbControlRCI.Items.Add(newTabItem);
tbControlRCI.SelectedIndex = tbControlRCI.Items.Count - 1;
My XAML only has a ChromeTabsControl that I place all of these dynamic Tabs and Browsers into.
Can anyone show the error of my ways?
EDIT:
Ok, thanks amaitland, I have tried a few different ways to do that and it just does not update for some reason. All I need is a textbox to show the address the Browser is on, so one way is fine. So I tried this:
Binding b = new Binding();
b.Mode = BindingMode.OneWay;
b.Path = new PropertyPath("Address");
b.ElementName = "RCIBrowser";
txtbxRCI.SetBinding(TextBox.TextProperty, b);
Thanks a bunch,
Hometownnerd
I have been trying to add Searchbar via UISearchController in my app. It does not show up on my navigation bar.I have added a navigation controller as a root view controller and have not changed anything but just the tint colour of it. I have tried few solutions but nothing works. I am using Swift 4.0 with Xcode 9 and running the app on IOS 11. Below is my code. Thanks in advance.
if #available(iOS 11.0, *) {
let sc = UISearchController(searchResultsController: nil)
sc.delegate = self
let scb = sc.searchBar
scb.sizeToFit()
scb.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
scb.tintColor = UIColor.white
self.navigationController?.navigationItem.searchController = sc
self.navigationController?.navigationItem.hidesSearchBarWhenScrolling = false
}
I don't know why but it will help you.
Add search controller in NavigationItem directly.
navigationItem.searchController = sc
navigationItem.hidesSearchBarWhenScrolling = false
Set the searchbar as your tableview header, worked for me.
self.tableView.tableHeaderView = self.searchController.searchBar
Maybe delete sc.delegate = self and put instead scb.delegate = self.
Also, I think you have to choose only one between scb.sizeToFit() and scb.heightAnchor.constraint(equalToConstant: 44.0).isActive = true because one excludes the other one. Hope it helps.
I am working on an Augmented Reality iOS app for which i am using ARKIT of iOS 11 beta. I am using ARSCNView(SceneKit) to render my .scn object. I have followed the sample given by apple in order to create an ARSession(https://developer.apple.com/sample-code/wwdc/2017/PlacingObjects.zip). Is it possible to place the 3D model with custom background instead of camera?
Like user can select the background color or can provide custom 2D photos as background?
Your view has a scene property where you can set the background to a color or an image:
view.scene.background.contents = UIColor.red
let myImage: UIImage = ...
view.scene.background.contents = myImage
I use shake motion callback of UIKit to change background contents. As #yaali said, CameraContents is used to store camera contents. Notice that we can't get background.contents if the camera has not launched, for example on viewWillAppear. I guess ARKit set the AVCaptureVideoPreviewLayer to ARSCNView.scene.background.cocntents.
override func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?) {
if CameraContents == nil {
CameraContents = sceneView.scene.background.contents;
return
}
if cameraBackGround == true {
sceneView.scene.background.contents = "Background_sky.png"
}else{
sceneView.scene.background.contents = CameraContents
}
cameraBackGround = !cameraBackGround
}
I want to add a button that show/hides the popover, similarly to the one of the DropBox app.
(In both landscape & portrait)
I have tried many solutions, but at this stage I don't even want to muddy the water with my attempts. If you've done this, or know how to do this, please send me in the right direction!
Thanks!
it appears it's quite simple.
Set some object to be delegate of splitViewController. In my case (I create all viewcontrollers programatically) that was appdelegate.
UISplitViewController* splitViewController = [[UISplitViewController alloc] init];
[splitViewController setViewControllers:#[navigationViewController1, navigationViewController2]];
splitViewController.delegate = self;
Implement delegate method to hide master in portrait orientation:
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
return UIInterfaceOrientationIsPortrait(orientation);
}
Actually add barButtonItem:
-(void)splitViewController:(UISplitViewController *)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)pc {
UINavigationController* slaveNavigationViewController = svc.viewControllers[1];
UIViewController* slaveViewController = slaveNavigationViewController.viewControllers[0];
[barButtonItem setTitle:#"Your master title"];
slaveViewController.navigationItem.leftBarButtonItem = barButtonItem;
}
In this method, you get barButtonItem which you customize and add to slaveViewController.
And last one, remove the button in landscape orientation:
- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
UINavigationController* slaveNavigationViewController = svc.viewControllers[1];
UIViewController* slaveViewController = slaveNavigationViewController.viewControllers[0];
[barButtonItem setTitle:#"Drops"];
slaveViewController.navigationItem.leftBarButtonItem = nil;
}
That's it.
There's a simpler, undocumented way to do it. For an existing UIButton:
[button addTarget: theSplitViewController action: #selector(toggleMasterVisible:) forControlEvents:UIControlEventTouchUpInside];
This target/action are the same as for the barButtonItem sent in the willHideViewController function.
I'm trying to write a game using F# and Silverlight and am struggling a bit with immutability.
I want to decouple the game from the view a little, so I put it in a module and made its update function return a new instance of the world-state, thus providing immutability.
The view (AppControl) is responsible for drawing the world.
However, I see no way around making the world a ref cell in the view.
Now, I think the mutable state is local enough to not cause any problems (please correct me, if I'm wrong), I am just curious, if someone can think of a way to avoid mutable state completely?
Here's the outline of the application, I tried to reduce the problem down to the essence:
open System
open System.Windows
open System.Windows.Controls
open System.Windows.Media
module Game =
type World = { State : int }
let init() =
{ State = 0 }
// immutable update loop
let updateWorld world =
{ State = world.State + 1 }
type AppControl() =
inherit UserControl()
let canvas = new Canvas()
let textBlock = new TextBlock()
let world = Game.init() |> ref // mutable world
let drawWorld (world : Game.World) =
textBlock.Text <- world.State.ToString()
// mutating game loop
let gameLoop world =
world := Game.updateWorld !world
drawWorld !world
()
do
canvas.Children.Add(textBlock)
base.Content <- canvas
CompositionTarget.Rendering.Add (fun _ -> gameLoop world)
type App() as this =
inherit Application()
let main = new AppControl()
do this.Startup.Add(fun _ -> this.RootVisual <- main)
The structure of your code looks fine - the mutable state is localized in the user interface (which is mutable anyway), so it is fine. You're not mutating the field from any closure, so you could use a mutable field (declared using let mutable world = ..) instead of ref cell.
To completely avoid the mutation, you can use asynchronous workflow (running on the GUI thread):
type AppControl() =
inherit UserControl()
let canvas = new Canvas()
let textBlock = new TextBlock()
let drawWorld (world : Game.World) =
textBlock.Text <- world.State.ToString()
// Asynchronous loop that waits for 'Rendering', updates
// the world & draws it and then continues waiting
let gameLoop world = async {
let! _ = Async.AwaitEvent CompositionTarget.Rendering
let newWorld = Game.updateWorld world
drawWorld newWorld
return! gameLoop newWorld }
do
canvas.Children.Add(textBlock)
base.Content <- canvas
gameLoop Game.init() |> Async.StartImmediate
The gameLoop function is asynchronous, so it doesn't block any thread. It is started using Async.StartImmediate, which means that it will run only on GUI thread (so accessing GUI elements & events from the body is safe). Inside the function, you can wait for event occurrence (using Async.AwaitEvent) and then do some action. The last line (return!) is a tail-call, so the function will continue running until the application is closed.