The following code worked properly prior to upgrading to Xcode 7.3;
func myMethod() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(CreateButtonObject.notifyButtonAction(_:)))
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(CreateButtonObject.notifyButtonAction(_:)))
tapGesture.numberOfTapsRequired = 1
}
#IBAction #objc func notifyButtonAction (sender: AnyObject) {
let userInfo:Dictionary<String,AnyObject!>
print("Sender from tap or longpress: \(sender)")
**let button = sender.view as! UIButton**
let soundName = button.currentTitle!
userInfo = ["sender" : sender]
NSNotificationCenter.defaultCenter().postNotificationName(sleepEZButtonActionNotificationKey, object: nil, userInfo: userInfo)
DDLogDebug("CreateButtonObject.notifyButtonAction: Notificaiton! ButtonViewController")
DDLogDebug("CreateButtonObject.notifyButtonAction: Posted Notification sleepEZButtonActionNotificationKey to initiate buttonAction")
DDLogDebug("CreateButtonObject.notifyButtonAction: Button Name: \(soundName)")
DDLogDebug("")
}
But now when I do this in Xcode 7.3 I get the following error on the line with sender.view ;
Ambiguous use of 'view'
followed by a compiler error.
Anyone know what's going on here and how to fix. Can't figure this out. Basically I need to get the UIButton attributes out of the UITapGesureRecognizer object that is created and then activated on a button press. Stuck.
Thanks in advance...
In the declaration func notifyButtonAction (sender: AnyObject), you have typed sender as AnyObject. But an AnyObject doesn't have a view. So in your line sender.view as! UIButton, the phrase sender.view is illegal.
Type sender as a UIGestureRecognizer if that's what it is: func notifyButtonAction (sender: UIGestureRecognizer). A gesture recognizer does have a view, so all will be well.
Related
I have a UINavigationController which includes 4 screens. Each has a back button respectively. Task: by pressing the back button on Controller4 get to Controller2, which will immediately switch to Controller1. I want to do this through a delegate (connection of 2 and 4 controllers), but I don’t understand how I can access the ViewController4.delegate = self property in Controller2. There is already an action for clicking and switching to 3Controller, to do something like
let storyboard = UIStoryboard(name: "VC4", bundle: nil)
guard let vc4 = story.instantiateViewController(withIdentifier: "VC4") as? VC4 else { return }
vc4.delegate = self
}
Please, help. How to link two controllers that are in completely different places in the project through a delegate (or something else)
P.S. This is my first time asking a question, sorry in advance if it's crooked
Example
protocol Controller2Delegate: AnyObject {
func showVC1()
}
class Controller2: UIViewController, Controller2Delegate {
// need to connect between 2 and 4 controller
let story = UIStoryboard(name: "VC4", bundle: nil)
guard let vc4 = story.instantiateViewController(withIdentifier: "VC4") as? VC4 else { return }
vc4.delegate = self //this is not work, and i already have same method for push to VC3
func showVC1() {
//any logic to call VC1 from VC2
//break point never called
}
class Controller4: UIViewController {
weak var delegate: Controller2Delegate?
func GoToVC1() {
//method who's call logic for pop to VC2
delegate?.showVC1
}// breakpoint is called
}
I'm creating a macOS SwiftUI app that opens a WKWebView to a specific URL.
Now I'm attempting to make a MenuItem mapped to a function that takes a screenshot of the WKWebView window, and saves it to ~/Pictures with a timestamp.
I tried to look for this via tutorials but only found iOS WKSnapShot type stuff.
While the "MenuItem" -> bind to -> First Responder -> #IBAction is something I'm kind of familiar with now, I'm not entirely sure how to call the WKWebView snapshotting and how to define it's timestamped name.
#IBAction func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?,
completionHandler: #escaping (NSImage?, Error?) -> Void)
{
}
This started shooting errors at me: #IBAction methods must have 1 argument
You just need to call the snapshot function on the webView. To get the webView snapshot function to be available, you need to make it available in the AppDelegate.swift
Then you can save it by using saveImage - which is linked in the handy function at this answer.
public let webView: WKWebView = WKWebView()
#IBAction func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration,
completionHandler: #escaping (NSImage *snapshotImage) -> Void)
{
self.webView.takeSnapshot(with: snapshotConfiguration) { image, error in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy_MM_dd_hh_mm_ss"
name = (formatter.string(from: Date()) as NSString) as String
if let image = image {
saveImage(name, image)
}
}
}
Performing this
self.performSegue(withIdentifier: "segueError2", sender: self)
right after receiving a message using:
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
drops a "Attempt to present UIViewController on simpleBrowerVC whose view is not in the window hierarchy!" error message.
Did the same in other places of the same ViewController (inside a: didStartProvisionalNavigation) and worked like a charm.
What I'm doing wrong?
FIXED!
Gave control to my current viewController, performing
UIApplication.shared.keyWindow?.rootViewController = self
UIApplication.shared.keyWindow?.makeKey()
My code worked fine in Xcode 6.2. After the update to Xcode 6.3 I had some Nullabilty Errors.
I could solve these errors after I downloaded the Parse SDK 1.7.1. So I deleted the old Parse framework files in my project and pasted the new ones into it. Additional I convert my code to the latest swift syntax "Edit/Convert/latest swift syntax". Now I haven't problems with Nullabilty Errors but several others.
In my project I have a simple Tableviewcontroller with the following code:
import UIKit
class HaendlerTableViewController: PFQueryTableViewController {
// Initialise the PFQueryTable tableview
override init!(style: UITableViewStyle, className: String!) { //1. Falialbe initialize init/style:className:)' cannot override a non-failable initializer
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Configure the PFQueryTableView
self.parseClassName = "Haendler"
self.textKey = "name"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! { //2. Ovverriding method with selector queryForTable has incompatitble typ () -> PFQuery
var query = PFQuery(className: "Haendler")
query.orderByAscending("name")
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell { //3. Ovverriding method with selector 'tableView:cellForRowAtindexPath:object:' has incompatible type '(UITableView, NSIndexPath, PFObject) -> PFTableViewCell
var cell = tableView.dequeueReusableCellWithIdentifier("HaendlerCell") as! HaendlerCell!
if cell == nil {
cell = HaendlerCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
// Extract values from the PFObject to display in the table cell
cell.haendlerName.text = object["name"] as! String!
var thumbnail = object["logo"] as! PFFile
var initialThumbnail = UIImage(named: "haendler")
cell.haendlerBild.image = initialThumbnail
cell.haendlerBild.file = thumbnail
cell.haendlerBild.loadInBackground()
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var detailScene = segue.destinationViewController as! HaendlerDetailViewController
// Pass the selected object to the destination view controller.
if let indexPath = self.tableView.indexPathForSelectedRow() {
let row = Int(indexPath.row)
detailScene.currentObject = objects[row] as? PFObject //4. Could not find an overload for 'subscript' that accepts the supplied agruments
}
}
}
I wrote the errors in a comment on the right side of the code and
below.
Falialbe initialize init/style:className:)' cannot override a non-failable initializer
Ovverriding method with selector queryForTable has incompatitble typ () -> PFQuery
Ovverriding method with selector 'tableView:cellForRowAtindexPath:object:' has incompatible type '(UITableView, NSIndexPath, PFObject) -> PFTableViewCell
Could not find an overload for 'subscript' that accepts the supplied agruments
I have the same errors when I make a new Swift project from the Parse Quickstart and add one Tableviewcontroller. In my old project was an objective-C bridging header which one I deleted because I had the oppurtunity to add the Parse SDK 1.7.1 directly in my Swift project.
Now I need help because I don't see what I have to change..
PS: Sorry for the mix of German and English code I'll adjust it once the project is running again
I had the same issue as I just updated Xcode to 6.3 about 20 minutes ago.
For your 2nd error, remove the '!' after 'PFQuery'. So it should now look like..
override func queryForTable() -> PFQuery {
This solved my problem in regards to that specific error.
I never used an init method as you did in your first error, but try removing it and see what you get. My PFQueryTableViewController works fine without it.
Had the same issues.
To solve the first initialise issue remove the '!' after 'override init'. Should look like this:
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) { //1. Falialbe initialize init/style:className:)' cannot override a non-failable initializer
super.init(style: style, className: className)
}
Do the same for the 2nd error after 'PFQuery'
override func queryForTable() -> PFQuery {
Hope its helpful. Since the latest update unwrapping elements usually needs to be revised for possible errors.
I want to know how you allow an action to be made by either pressing the return key on the software keyboard or by tapping a UIButton.
The UI button is already set up to perform an IBAction.
How do I also allow users to press the return key on the keyboard to perform the same action?
Make sure your class extends the UITextFieldDelegate protocol
SomeViewControllerClass : UIViewController, UITextFieldDelegate
You can perform action as follows:
override func viewDidLoad() {
super.viewDidLoad()
self.textField.delegate = self
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
//textField code
textField.resignFirstResponder() //if desired
performAction()
return true
}
func performAction() {
//action events
}
UPDATE
If your deployment target is iOS 9.0 or later, you can connect the “Primary Action Triggered” event of your text field to an action, like this:
ORIGINAL
Make your view controller adopt the UITextFieldDelegate protocol.
Set your text field's delegate to your view controller.
Implement textFieldShouldReturn: to call your action.
Swift 4.2 :
Other approach for the textfield created programmatically and doesn't need delegate :
MyTextField.addTarget(self, action: #selector(MyTextFielAction)
, for: UIControl.Event.primaryActionTriggered)
And then perform your action like below :
func MyTextFielAction(textField: UITextField) {
//YOUR CODE can perform same action as your UIButton
}
If your deployment target is iOS 9.0 or later, you can connect the “Primary Action Triggered” event of your text field to an action, like this:
I was not able to get the "Primary Action Triggered" to work as suggested. I used "Editing Did End" and that works for now Screenshot of Editing Did End
Here is a complete example, with both:
button-action to write and also to clear label and text when pressing button repeatedly it alternates both actions
return-in-keyboard when pressing key it triggers action and also resigns first responder
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var label1: UILabel!
var buttonHasBeenPressed = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
textField1.delegate = self
}
#IBAction func buttonGo(_ sender: Any) {
performAction()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
performAction()
return true
}
func performAction() {
buttonHasBeenPressed = !buttonHasBeenPressed
if buttonHasBeenPressed == true {
label1.text = textField1.text
} else {
textField1.text = ""
label1.text = ""
}
}
}