Adding NSTextFields together Swift 3 XCode 8 - swift

Any anyone explain the syntax in adding two or more textfields together in Swift 3 inside XCode 8. This is for a desktop application, not IOS. NSTextField Control.
I need precision to the tenth's place. So I guess a float will be necessary.
Furthermore, how can I do the adding automatically when the textbox is updated, so it is adding on the fly. So I do not have to put in a "Calculate" button. Do I need to do anything special to sanitize the fields to prevent alphas to be typed?

Not the most helpful group. Here's what I found out works. added NSTextFieldDelegate to the top View Class Controller like so
class View1Controller: NSViewController, NSTextFieldDelegate
Then: in my viewdidload
txtField.delegate = self
Then I could override the function:
override func controlTextDidChange(_ obj: Notification) { run some code here }

Related

How to disambiguate global and local methods in Swift?

I want to use kind of SwiftUI-like functional style of configuring the UI, for example by providing [a global] method hide(view: UIView) instead of writing view.isHidden = true.
Now this works fine but for reverse logic I want to have the global method show() but within context of an UIViewController it conflicts with the class method show(sender: Any).
Is there any language trick I can you in order not to have to write MyAppName.show() each time I use it?
Your title is a bit inaccurate. You already know how to disambiguate it. The question is about how to do so without repeating the module name. Unfortunately, I don't think there's any such way.
I found out that Swift compiler seems to be overreacting, as one method has 2 arguments and my method has 1 argument. What's the reason to write "nearly matches" and breaking compilation is unclear to me.
However, I found the solution:
extension UIViewController{
func show(_ view: UIView) { view.isHidden = false }
}

Swift: Referencing variables in one class from another function and/or class

trying a few things out in Swift. I’m trying to get some things that seem muddled to me straightened out - mostly to do with how I deal with variables and referencing them in a project.
What I am trying to do is keep a variable (based on a struct) defined in ViewController accessed and updated from various other functions within an application.
So, a brief outline of the code I have is here. I actually wrote a smaller app to test my ideas out before applying them to something more complex.
I started in XCode with a Swift document based application for Mac OSX.
In ViewController.swift I have:
import Cocoa
class ViewController: NSViewController {
var myText = "Hello, some text"
#IBOutlet weak var textView1: NSTextField!
#IBAction func Button1(_ sender: Any) {
myText = "This is button 1 clicked"
myText = setText( thisText: &myText )
textView1.stringValue = myText
}
#IBAction func Button2(_ sender: Any) {
print("Button 2")
myText = "This is button 2 clicked"
textView1.stringValue = myText
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
textView1.stringValue = myText
}
override func viewDidAppear() {
let document = self.view.window?.windowController?.document as! Document
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
In SetText.swift, I have this:
import Foundation
func setText( thisText: inout String) -> String {
thisText = "Function"
return thisText
}
I liked the idea of sending variables to the Set Text function and then returning it, but thinking about it more makes me think that actually this could end up like a proverbial bowl of spaghetti with functions calling functions and who know what else. So I was thinking that something like this would probably make more sense:
import Foundation
func setText( thisText: inout String) {
let vc = ViewController()
// Read the variable from View Controller
var myTextHere = vc.myText
myTextHere = myTextHere + " More text"
// Set the variable in ViewController here
vc.myText = myTextHere
}
From my reading around on this subject, if I call ViewController(), it will create anew instance of the view (is that right, or am I misreading?). That’s already happened, so what I need is to reference the ViewController that called the function setText, or rather that owns that particular instance of code. As I’m thinking about a document based application, I’d obviously want to keep all instances of myText with each document’s ViewController.
My aim is to create something a bit more complex, using a variable based on a Struct to keep everything together. So:
myCard.image // holds a bitmap image
myCard.size // holds the size of the image
And so on. being able to access it in the form of ViewController().myCard to both read and write to is what I am thinking I need to do.
What I don’t want to do is use global variables.
Thanks.
I'm having a hard time seeing much correlation between the title of your question and the body of your question. In fact, I'm not even entirely sure that there's a question being asked. That said, I'll try to address the questions you appear to be asking (re-written how I think they're intended):
When you initialize a new view controller, does it create a new view?
Yes. There is a view property for every view controller, and it's not a shared component or a singleton or anything else like that. There is one main view for every view controller. It's almost certainly composed of dozens of other subviews, but there is one view that is the view for every view controller.
Is there a way to get metadata about the state of a view controller from outside, preferably in the form of a struct?
Absolutely. First, you'd need to define that Card struct. I'd recommend doing it in the same file as the view controller itself. You can define it outside of the view controller, or if you want stricter coupling and namespacing, you can do it inside the view controller. Just be aware that doing that latter would mean that the type name, when referenced outside the view controller, would be ViewController.Card rather than just Card.
Then you'd want to create either a computed property (var card: Card) or a method (func card() -> Card) on your view controller which builds and returns one of those based on the state. It sounds like you're already leaning toward the property approach.
Note: I would absolutely advise against having one that is a normal get/set property because then you'd have to constantly update it and modify it. The best thing to do is have a computed property which builds it on the fly. So when the property is called, it reaches into all your components to get the info you want (like image sizes, strings, etc) and then packages up and hands off the Card metadata struct. Doing it on-demand like this eliminates unnecessary complexity and consolidates the metadata logic into one place.
Some dangerous things in your code example:
I can't think of a good reason to implement viewDidAppear() but not call super.viewDidAppear(). Unless you have an enormously compelling reason to leave that out (I honestly can't think of a single one), do not do so.
I don't see any good reason for your first implementation of your setText(thisText:) method. The way you use it in your Button1(_ sender: Any) IBAction functionally does absolutely nothing. That method in general is screwy for several reasons: it's got an upper-case method name, sets the textView text by trying to assign to stringValue for some super strange reason, and does in three lines what could be done in one:
textView1.text = "This is button 1 clicked"
The second implementation of setText(thisText:) makes even less sense than the previous. The two biggest problems being 1) that you don't even use the thisText argument passed in, and 2) your method, which is called 'set text' is creating a whole new view controller every single time it gets called? That's a huge violation of "doing what it says on the tin." Methods should have a single responsibility and shouldn't do anything beyond that responsibility. I'd never in a million years look at a method called setText and think "I'll bet this initializes a view controller." Never.
I see this question has already been downvoted a bit (not by me), and I'd like to take a moment to coach you in using Stack Overflow: Ask clear, concise, specific questions about clear, concise, specific topics. As I said at the top of my answer, there doesn't appear to be a question anywhere in your post. I had to kind of make some up that I inferred from what you wrote.
Remember: coding isn't just wiggling your fingers while you think about an app. If you're doing the hard work of good engineering, you'll likely spend a ratio of about 10:1 (or more!) of staring at your screen to actually typing any code. Every time you write a line of code, you should be asking yourself, "Why am I writing this line of code? Is this necessary? Am I reinventing the wheel?)
Good luck!

Implementing responder action in Swift

I am having difficulty implementing an action for an NSMenuItem in Swift. Normally, you implement the action like this in Objective-C:
- (void) asdf:(id)sender
This works perfectly fine, after setting up the action in the first responder like so:
However, after rewriting my view controller in Swift, the following new method doesn't seem to be called:
func asdf(sender: AnyObject?)
It doesn't seem to work, even though both the Obj-C and Swift versions are for the same view controller subclass.
In Swift 3.0 you'd define it as:
func asdf(_ sender: Any)
Why?
If you use _ you can drop parameter name when calling a function, so now you can call it like:
object.asdf(object)
Instead of:
object.asdf(sender: object)
Moreover, with Swift you'd use Any instead of AnyObject in this context. You can find more on differences between those here.

iOS 10 issue with storyboard custom view classes

Does anybody know why the ZoomingPDFViewer Apple Sample Code project no longer works? It was working prior to the iOS 10 release but now it keeps returning a unrecognized selector error when calling [PDFScrollView setPDFPage:].
It seems like the custom classes set in the storyboard are no longer being instantiated.
I had the same issue. It seems that the auto conversion to Swift 3 doesn't work well with IBs.
There are two options:
a) You can set the argument label--i.e.the parameter name to be shown externally--to _. For example,
#IBAction func setPDFPage(_ sender: AnyObject) {
// ...
}
b) You can remove the IBAction connection in the IB and re-set it. Notice instead of the previous setPDFPage(sender:) the connection will say setPDFPageWithSender(sender:) or something like that. (I didn't actually try it with the code in question, but writing from experience here.)
The same is true for segues.

IBOutlets in NSCollectionViewItem are nil

I am having a problem where it seems I am able to add items to a collection view, and have the prototype cells I created from a subclass of NSCollectionViewItem, but when I try to change the labels in order to display the data from the is get errors because they are nil, even though I connected them from the interface builder.
I also checked out the representedObject property by printing by attacked a mouseup function to the cell, and it was working fine. It only falls apart when I attempt to assign to the stringValue of the apparently nonexistent outlets.
Down below you can see my storyboard and the controller for the item views.
The Label objects are represented down below as the two #IBOutlets.
representedObject is being aliased as var morpheme : Morpheme?
Here in the main window controller I am testing out just adding the Morpheme objects to the collection with test values that I'm wanting to populate the Labels with.
The display shows the cells in a list, but when I click them it crashes due to a nil value from the apparently uninstantiated outlets. If you look in the console Morpheme 3 was printed successfully, so the data model made it in. Is there anything more I need to do? There is a lot of stuff about using the binding menu floating around, but I haven't played around much with it.
That is very interesting problem which already gained a lot of traction. The problem seems to be a bug in Cocoa so when items created from prototype, their outlets dont get hooked.
Look what happens when prototype is created:
Then when actual instance is created the outlets are nil:
So my recommendation would be to use one of 2 solutions:
Use nibs and NSCollectionViewDataSource to create collection view items based on Views. Look for the last answer here:
Cocoa - Where is the link between a NSCollectionView and a NSCollectionViewItem? Xcode 6 Bug?
Or just see examples with keyword: "makeItemWithIdentifier"
Dont use outlets and use data binding as I did in my example. I bound my text edit to represented object:
And here is my code in controller:
class ViewController: NSViewController {
dynamic var collectionViewData = [String]()
#IBOutlet weak var collectionView: NSCollectionView!
override func viewDidLoad() {
super.viewDidLoad()
guard let proto = self.storyboard?.instantiateControllerWithIdentifier("collectionViewItem") as? CustomCollectionViewItem else { return }
collectionView.itemPrototype = proto
collectionViewData.append("One")
collectionViewData.append("Two")
}
My final picture is (you can see I bound label to the actaul string in the array):