I have a webview loading a local HTML page after pressing a button in a view controller. How would I put a button under the webview to load different content in the same web view?
ViewController has no extra code entered just a button in storyboard with a present modal segue to the webView controller
webView has the following code.
//
// WebViewer.swift
// TestWebView
//
// Created by Colin McGarry on 13/03/15.
// Copyright (c) 2015 Colin McGarry. All rights reserved.
//
import UIKit
class WebViewer: UIViewController {
var page = "2page"
#IBOutlet weak var webView: UIWebView!
#IBAction func close(sender: AnyObject) {
println(sender.tag)
dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func reLoad(sender: AnyObject) {
println(sender.tag)
page = "1page"
webView!.reload()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if let htmlFile = NSBundle.mainBundle().pathForResource(page, ofType: "html"){
let htmlData = NSData(contentsOfFile: htmlFile)
let baseURL = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath)
webView.loadData(htmlData, MIMEType: "text/html", textEncodingName: "UTF-8", baseURL: baseURL)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Under the webView i've placed two buttons, one to close and go back to the viewcontroller, the other I wanted to reload a different webpage in this view.
I tried an if statement with the sender.tag of the reload button but it wasn't recognised. Neither was the segue identifier from the first viewController
I found a solution from an unanswered question.
i changed my reload() function to.
#IBAction func reLoad(sender: AnyObject) {
println(sender.tag)
page = "1page"
if let htmlFile = NSBundle.mainBundle().pathForResource(page, ofType: "html"){
let htmlData = NSData(contentsOfFile: htmlFile)
let baseURL = NSURL.fileURLWithPath(NSBundle.mainBundle().bundlePath)
webView.loadData(htmlData, MIMEType: "text/html", textEncodingName: "UTF-8", baseURL: baseURL)
}
}
I'm thinking that it would probably be better to put the repeated code in a function and call it each time.
Related
I have two ViewControllers.
On VC1 I have search criteria and on VC2 I have the search results. If you want to go from VC2 to VC1 the VC2 is dismissed.
On VC1 I have an NSButton(style Check, type Switch) which by default I want it to be in ON state. The purpose of the NSButton is to include photos in the results.
If the user unchecks the button and presses search, it will go on to VC2 showing the search results without photos.
BUT when the user goes back to VC1 for a new search that's where the unwanted behaviour occurs:
The NSButton is unchecked(i want it to be checked by default, every time the user is at the VC1. Also, the button is nil.
Why is this happening, and how can i make it the button box to be ticked everytime the VC2 is dismissed?
I tried enabling it and setting it to ONState but as its nil it would crash.
To set a state every time your controller opens use the method
-(void)viewWillAppear
To let viewControllers communicate with each other you can implement delegates. Here is a pretty good tutorial: Link
Another approach is to communicate with Notifications -> Link
Or you can set values on methods like prepareForSegue - depending on what you use to imstantinate your controllers.
I have managed to make it perform the way I want it by adding
switch.state=1
just before the segue from VC1 to VC2 is performed.
However, I don't think this is the most elegant solution as the button is still nil.
UPDATE:
I have figured out that the issue occurs as when it goes from VC1 to VC2 the VC1 becomes nil, when the VC2 is dismissed it becomes nil as well. Hence the crash. One solution is to use delegates.
VC1:
class FirstViewController: UIViewController,SecondViewControllerProtocol {
#IBOutlet var firstName: UITextField!
#IBOutlet var lastName: UITextField!
#IBOutlet var subscribeSwitch: UISwitch!
#IBAction func goToSecondVC(_ sender: Any) {
let viewController = self.storyboard?.instantiateViewController(withIdentifier: String(describing: SecondViewController.self)) as! SecondViewController
viewController.delegate = self
self.present(viewController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func dismissViewController() {
if let viewController = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController"){
subscribeSwitch.isOn=true
}
}
}
VC2:
protocol SecondViewControllerProtocol {
func dismissViewController()
}
class SecondViewController: UIViewController {
var delegate:SecondViewControllerProtocol!
#IBAction func goBackToFirstVC(_ sender: Any) {
self.dismiss(animated: true) {
self.delegate!.dismissViewController()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have a view that opens another view Controller as popover
the popover uses an image picker and displays the chosen image in an imageView.
The parent also has an imageView with an IBoutlet named profiler and before dismissing the popover i would like the parent view to get the chosen image.
How would i go about accessing parent and sending the image from the popover to the parent view
below is code from the popover view controller:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
picker.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
let chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage //2
myImageView.contentMode = .scaleAspectFit //3
myImageView.image = chosenImage //4
myImageView.layer.borderWidth = 1
myImageView.layer.masksToBounds = false
myImageView.layer.borderColor = UIColor.black.cgColor
myImageView.layer.cornerRadius = myImageView.frame.height/4
myImageView.clipsToBounds = true
dismiss(animated:true, completion: nil) //5
}
thanks for any help rendered
Use a callback closure, it's less effort than delegate/protocol
In the popover view controller add a property
weak var callback : ((UIImage) -> ())?
Call it in didFinishPickingMediaWithInfo before dismiss
callback?(chosenImage)
In the parent view controller after creating the controller add
popoverViewController.callback = { image in
// do something with the image
}
popoverViewController is the popover view controller instance
you should create protocol
protocol PopOverImagePickerDelegate: NSObjectProtocol {
func didSelect(image: UIImage)
}
inside your PopoverViewController create
weak var delegate: PopOverImagePickerDelegate?
before navigating to PopoverViewController from ParentViewController set
popOverViewController.delegate = self
and then create
extension ParentViewController: PopOverImagePickerDelegate {
func didSelect(image: UIImage) {
//do stuff
}
}
and when image picked inside PopoverViewController just call
self.delegate?.didSelect(image: image)
I have a view with a series of action buttons. All these buttons are connected to a function that allows me to play a video. I retrieve the name of the video in the button title. The problem is that I need to press the button twice to get the right video, otherwise the last video is playing
Here is the code that is associated.
import UIKit
import AVKit
import AVFoundation
class levresViewController: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var varVue2="toto"
var playerController = AVPlayerViewController()
var player:AVPlayer?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let videoString:String? = Bundle.main.path(forResource: varVue2, ofType: ".mp4")
if let url = videoString {
let videoURL=NSURL(fileURLWithPath: url)
self.player = AVPlayer(url: videoURL as URL)
self.playerController.player = self.player
}
// Do any additional setup after loading the view.
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playVideo(_ sender: UIButton) {
varVue2=sender.currentTitle!
self.present(self.playerController,animated:true,completion:{
self.playerController.player?.play()
})
}
}
I am new to Mac OSX and with Apple promoting the fact that the bodies of code are becoming similar decided to tell the folk I am writing code for we should be able to do a Mac OSX version. iPhone and iPad versions are all good and about to release second version so no issues there.
So I am subclassing NSWindowController to get access to the Toolbar and worked out how to remove and add items on the toolbar, but for the life of me I can not get one NSViewController (firstViewController) to dismiss and bring up the second NSViewController (secondViewController) in the same NSWindowController.
So the 2 issues are that
1. I want to be able to performSegueWithIdentifier from the first NSViewController in code and
2. bring up the second NSViewController by replacing the first NSViewController in the same NSWindowController.
If I add a button to the firstViewController and put a segue to the secondViewController then when I select the button the secondViewController comes up just fine but in a seperate window not the same NSWindowController that I want it to and the firstViewController does not get replaced but stays in the NSWindowController.
So I know the segue idea will work but its not working in code and when I do insert the segue from a button it works but into a seperate NSViewController that is not part of the NSWindowController.
I am trying to find some programming guide from Apple on the issue but no luck so far.
Here is an overview from my Storyboard:
Here is my NSWindowController subclassed and the func loginToMe2Team is trigger from the NSToolBar and its working just find as the print statements show up on the console.
import Cocoa
class me2teamWindowsController: NSWindowController {
#IBOutlet var mySignUp : NSToolbarItem!
#IBOutlet var myToolbar : NSToolbar!
let controller = ViewController()
override func windowDidLoad() {
super.windowDidLoad()
print("window loaded")
}
override func windowWillLoad() {
print("window will load")
}
#IBAction func logInToMe2Team(sender: AnyObject){
controller.LogIn() //THIS IS THE FUNC I AM TESTING WITH
}
#IBAction func signUpToMe2Team(sender: AnyObject){
controller.signUp()
}
Here is my NSViewController subclassed with the func LogIn. Its getting selected just fine but the performSegueWithIdentifier is not. And I did cut and past the Identifier to make absolutely sure it was the same.
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet weak var theWebPage: WebView!
#IBOutlet weak var progressIndicator: NSProgressIndicator!
override func viewDidLoad() {
super.viewDidLoad()
let urlString = "https://thewebpage.com.au"
self.theWebPage.mainFrame.loadRequest(NSURLRequest(URL: NSURL(string: urlString)!))
}
override func viewDidAppear() {
}
func LogIn() {
print("I logged in")
self.performSegueWithIdentifier("goToTeamPage", sender: self)
//THIS IS THE BIT THATS NOT WORKING
}
func signUp() {
print("I have to sign up now")
}
override var representedObject: AnyObject? {
didSet {
}
}
func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!)
{
self.progressIndicator.startAnimation(self)
}
func webView(sender: WebView!, didFinishLoadForFrame frame: WebFrame!)
{
self.progressIndicator.stopAnimation(self)
}
}
You need to use a custom segue class (or possibly NSTabViewController if it’s enough for your needs). Set the segue’s type to Custom, with your class name specified:
…and implement it. With no animation, it’s simple:
class ReplaceSegue: NSStoryboardSegue {
override func perform() {
if let src = self.sourceController as? NSViewController,
let dest = self.destinationController as? NSViewController,
let window = src.view.window {
// this updates the content and adjusts window size
window.contentViewController = dest
}
}
}
In my case, I was using a sheet and wanted to transition to a different sheet with a different size, so I needed to do more:
class ReplaceSheetSegue: NSStoryboardSegue {
override func perform() {
if let src = self.sourceController as? NSViewController,
let dest = self.destinationController as? NSViewController,
let window = src.view.window {
// calculate new frame:
var rect = window.frameRectForContentRect(dest.view.frame)
rect.origin.x += (src.view.frame.width - dest.view.frame.width) / 2
rect.origin.y += src.view.frame.height - dest.view.frame.height
// don’t shrink visible content, prevent minsize from intervening:
window.contentViewController = nil
// animate resizing (TODO: crossover blending):
window.setFrame(window.convertRectToScreen(rect), display: true, animate: true)
// set new controller
window.contentViewController = dest
}
}
}
I have a question about swift,
I made a popover controller in a UIViewController,which display a list of books
and when the user click on one of the books, the label on the viewController should be updated with the name of the selected book.
But in my case when I select a name of a book, the label does not update
here is the code :
// View Controller
import UIKit
class ViewController: UIViewController,UIPopoverControllerDelegate {
var popoverController : UIPopoverController? = nil
#IBOutlet var bookName : UILabel
var BookNameString : String?{
didSet{
configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let detail = self.BookNameString {
if let label = bookName {
label.text = detail
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func Click(sender : UIButton) {
var tableView:TableViewController = TableViewController(style: UITableViewStyle.Plain)
var popoverContent:UINavigationController = UINavigationController(rootViewController: tableView)
self.popoverController = UIPopoverController(contentViewController: popoverContent)
self.popoverController!.delegate = self
self.popoverController!.presentPopoverFromRect(sender.frame, inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
and here is the code of the TableViewController when a row is selected:
// TableViewController
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!){
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var details = storyboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController
var keyString = bookSectionKeys[indexPath.section]
var bookValues = book.booksLetters[keyString]!
var selectedBookString = bookValues[indexPath.row]
var selectedBookValues = book.bookDictionary[selectedBookString]!
details.BookNameString = selectedBookString
}
I was able to solve this problem a few weeks ago and I want to share the solution with you :)
I solve it using protocols.
OK Here what I did in details:
First I created a protocol in the view that I want it to display inside the popover and I named the protocol "DismissPopoverDelegate"
protocol DismissPopoverDelegate{
func didSelectBook(SelectedBook:String)
}
Then I declared a variable of type DismissPopoverDelegate and name it "delegate"
var delegate: DismissPopoverDelegate?
Then in the didSelectRowAtIndexMethod:
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!){
var keyString = bookSectionKeys[indexPath.section]
var bookValues = book.booksLetters[keyString]!
var selectedBookString = bookValues[indexPath.row]
delegate?.didSelectBook(selectedBookString)
}
After that inside the View that contains the popover (View Controller), I set the delegate of the view:
class ViewController: UIViewController, DismissPopOverDelegate, UIPopoverControllerDelegate{
Then to make the view confirm to the protocol DismissPopOverDelegate, I implement the method "didSelectBook" Inside the view:
func didSelectBook(SelectedBook:String){
popoverController!.dismissPopoverAnimated(true) // This is Optional
bookName.text = SelectedBook // Make the label text equal to the selected book From the table
}
Finally, I set the delegate to the tableView to View Controller
tableView.delegate = self
That's it :)
Here is the full code of the viewController that contains the popover
import UIKit
class ViewController: UIViewController, DismissPopOverDelegate, UIPopoverControllerDelegate{
#IBOutlet var booksbarButton : UIBarButtonItem
#IBOutlet var bookName : UILabel
var popoverController : UIPopoverController? = nil
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func showTableView(sender : UIBarButtonItem) {
var tableView:TableViewController = TableViewController(style: UITableViewStyle.Plain)
tableView.delegate = self
var popoverContent:UINavigationController = UINavigationController(rootViewController: tableView)
self.popoverController = UIPopoverController(contentViewController: popoverContent)
popoverController!.delegate = self
self.popoverController!.presentPopoverFromBarButtonItem(booksbarButton, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
}
func didSelectBook(SelectedBook:String){
popoverController!.dismissPopoverAnimated(true)
bookName.text = SelectedBook
}
}