How to take a screenshot in XCUITest during press&hold? - swift

I need to take a screenshot in the middle of zoom/pan/rotate, i.e. I expect some code like this:
element.startPressAndHold(.twoTouches)
// at this point my app renders differently, so I capture a screenshot
// for snapshot testing
let shot = element.screenshot()
element.stopPressAndHold()
XCUIElement in fact has something similar for keys:
XCUIElement.perform(withKeyModifiers: .command) {
let shot = element.screenshot()
}
but I can not find something similar for mouse/touches/gestures.
Is there a trick to achieve this?

Related

Does SwiftyJson make parsing swift json faster?

I've recently made a weather that gets data from open weather map, but it takes forever for the parsed data to show up on the screen...
With code like this:
let tempF = jsonResult["tempFahrenheit"]
I know the data is fast because I watch the url result show up immediately in the console, so would swiftyjson speed up displaying data on the screen? Is there a swiftyjson for Swift 3??
The code you have posted doesn't appear to update any UI element on the screen.
If there is another place where you are updating the UI with something like
mylabel.text = someVariable
and the UI is still laggy, it maybe because you have not wrapped the UI
change in the main thread.
The correct way to do the update above would be
DispatchQueue.main.async { mylabel.text = someVariable }
Call API> Get Response> Parse Data > Update UI [It should be in main queue]
Write your UI update related code in main queue like below ...
DispatchQueue.main.async {
textFiled.text = yourText
imageview.image = yourImage
.......
}

How to write if and else statement more elegantly in Swift

I'm having a bit of a brain fart in Swift and I know this code could be written better. Basically what it is, I have two images and I check if a value is over 3 to show an image and hide the other.
currently I have it like this
let greaterThanThree = value > 3
image1.isHidden = greaterThanThree
image2.isHidden = !greaterThanThree
But I feel like there is a more elegant way to write this.
I'd write it like this:
image1.isHidden = value > 3
image2.isHidden = !image1.isHidden
Anything shorter than that is just code golfing.
There seems to be a rule here that exactly one of these two views should be visible at all times. If so, I'd create, as part of my view controller's viewDidLoad, an instance of this struct:
struct AlternateViews {
let views : [UIView]
init(_ v1:UIView, _ v2:UIView) {
views = [v1,v2]
}
func hide(first:Bool) {
views[0].isHidden = first
views[1].isHidden = !first
}
}
let alternateViews = AlternateViews(image1, image2)
Okay, that's a lot of work to set up initially, but the result is that later you can just say
self.alternateViews.hide(first: value > 3)
The struct is acting as a tiny state machine, making sure that your view controller's views remain in a coherent state. This technique of moving the rules for state into utility structs attached to your view controller is recommended in a WWDC 2016 video and I've been making a lot of use of it ever since.
If you have more pairs of alternating views, just make and maintain more instances of the struct.
(If the rule that I've assumed is not quite the real rule, make a struct that does express the real rule.)
You can do this:
(image1.isHidden, image2.isHidden) = (value > 3) ? (true, false) : (false, true)
Basically if the value is greater than 3, the first image will be hidden and the second one won't. Otherwise, the second image will be hidden and the first one will not.

How to setup printing in cocoa, swift?

I have made printing functionality for custom NSView of NSPopover by the assigning the following action to button for this NSView in mainController:
#IBOutlet var plasmidMapIBOutlet: PlasmidMapView!
#IBAction func actionPrintfMap(sender: AnyObject)
{
plasmidMapIBOutlet.print(sender)
}
It is working, but the print window has no option for Paper Size and Orientation, see screenshot below.
What should I do to get these options in the print window?
And, how to make the NSView fitting to the printable area? Now it is not fitting.
I have figured out some moments, but not completely. So, I can setup the printing by the following code
#IBAction func actionPrintMap(sender: AnyObject)
{
let printInfo = NSPrintInfo.sharedPrintInfo()
let operation: NSPrintOperation = NSPrintOperation(view: plasmidMapIBOutlet, printInfo: printInfo)
operation.printPanel.options = NSPrintPanelOptions.ShowsPaperSize
operation.printPanel.options = NSPrintPanelOptions.ShowsOrientation
operation.runOperation()
//plasmidMapIBOutlet.print(sender)
}
But, I still have problem. From the code above I can get only orientation (the last, ShowsOrientation), but not both PaperSize and Orientation. How can I manage both ShowsPaperSize and ShowsOrientation?
Finally I have found the answer which is simple to write but it is not really obvious from apple documentation.
operation.printPanel.options.insert(NSPrintPanelOptions.showsPaperSize)
operation.printPanel.options.insert(NSPrintPanelOptions.showsOrientation)
The problem in the code originally posted is that options is being assigned twice, so the first value assigned, ShowsPaperSize is overwritten by the value ShowsOrientation. That's why you only see the ShowsOrientation option in the dialog.
By using multiple insert operations, you are adding options rather than overwriting each time. You can also do it this way which I think reads better:
operation.printPanel.options.insert([.showsPaperSize, .showsOrientation])
And finally, it also works to "set" the options, and by supplying the existing options as the first array value, you achieve the affect of appending:
operation.printPanel.options = [
operation.printPanel.options,
.showsPaperSize,
.showsOrientation
]
(The first array element operation.printPanel.options means that the old options are supplied in the list of new options.)

AppleWatch Speech-to-Text functionality not working

I am trying to implement Speech-to-text feature for watchkit app.
I referred this question which has sample code.
Following is the code I tried:
self.presentTextInputControllerWithSuggestions(["Start it", "Stop it"], allowedInputMode: .Plain, completion: { (selectedAnswers) -> Void in
if selectedAnswers.count > 0 {
if let spokenReply = selectedAnswers[0] as? String {
self.label.setText("\(spokenReply)")
}
}
})
label is a label to display text I speak.
When I run it, it shows the screen where you are supposed to speak (Siri kind of screen) and you have two options on top: ‘Cancel', and ‘Done'. Once I am done speaking, I tap on ‘Done’ but screen doesn’t go away or shows me initial screen, I always have to tap on ‘Cancel’ to go back, and I don’t get any speech data in form of text. I checked it and seems like selectedAnswers is always an empty array, unless I tap on the "Start it"/"Stop it" options.
Can anyone help me with this? I want to show the spoken message on label. I have code inside awakeWithContext method in InterfaceController.swift file, am I supposed to put it somewhere else?
I am using iPhone with iOS 9 beta 2 and watchOS 2 beta on AppleWatch.
Thanks!
You can ask for user input and give him suggestion (see Swift example bellow).
self.presentTextInputControllerWithSuggestions(["suggestion 1", "suggestion 2"] allowedInputMode: .Plain, completion: { (answers) -> Void in
if answers && answers.count > 0 {
if let answer = answers[0] as? String {
println("\answer")
}
}
})
If suggestion is nil it goes directly to dictation. It is not working on the simulator but it is on real watch.
Your approach is correct but something is wrong with your SIRI , try changing the language.
It should work like these.

DWT togglebutton: does it even work?

I'm not sure if we are just 20 people in the world using dart right now and maybe just 10% of us try to use widgets..anyway, I seem not to understand if I'm doing something wrong with DWT or there is a bug. Here is a very simple example. I don't understand why the event are not even fired.
void main() {
ui.HorizontalPanel panel = new ui.HorizontalPanel();
ui.ToggleButton t1;
t1= new ui.ToggleButton.fromText("click",handler: new event.ClickHandlerAdapter((event.ClickEvent e) {
hans(panel,t1);
} ));
ui.ToggleButton t3;
t3 = new ui.ToggleButton.fromText("click");
t3.addClickHandler(new event.ClickHandlerAdapter((event.ClickEvent event) {
window.alert("Stop poking me!");
}));
panel.add(t1);
panel.add(t3);
ui.RootLayoutPanel.get().add(panel);
}
void hans(ui.Panel panel,ui.ToggleButton button){
var iter = panel.iterator();
while (iter.moveNext()) {
var butt = iter.current;
if (butt is ui.ToggleButton){
if (butt != button) {
butt.setDown(true);
}
}
}
Not really an answer to your question, but something I've noticed:
Not sure if bug or by design, but seems like the first node of a Tree does not handle clicks properly. I've created a tree with two ui.Label(s) in it and the first ui.Label does not respond to clicks. No aparent reason for that.
If I insert these ui.Label(s) in reversed order the situation is still the same: the first ui.Label (the other ui.Label, this time) does not respond to clicks.
So, I've circumvented the trouble by adding a Label in the beginning as "/" which is absolutely useless but does not need to respond to any clicks anyway.