Does SwiftyJson make parsing swift json faster? - swift

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
.......
}

Related

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

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?

How to guarantee one function runs after another in the Grand Central Dispatch?

Basically, I want to upload some images before I run other functions that rely on the image being uploaded. I think I may have a misunderstanding of what GCD is/how the threads work. I want function 1 and 2 to happen AFTER I upload the images. They are both quick to execute but rely heavily on the upload images to be complete. Maybe I shouldn't use GCD (as I want to implement a waiting indicator)? I just can't seem to get this to execute properly
if goToHome {
DispatchQueue.global().async {
DispatchQueue.main.sync {
self.uploadImages() // Uploads the images, takes a good amount of time to execute
function1()
function2()
}
}
Functions 1 and 2 keep running before the upload images get completed as they take much less time to execute.
The basic pattern in Swift is to do work such as uploading on a background thread, then call a completion function on the main thread and continue work based on whether or not your upload finished successfully.
Generally you'll call back onto the main thread in case you need to do something with the user interface such as setting a progress indicator (which has to happen on the main thread).
So something like this:
func uploadInBackground(_ images: [Image], completion: #escaping (_ success: Bool) -> Void) {
DispatchQueue.global(qos: .background).async {
var success = true
// upload the images but stop on any error
for image in images {
success = uploadImage(image) // upload your images somehow
guard success else { break }
}
DispatchQueue.main.async {
completion(success)
}
}
}
func mainThreadUploader() {
let images = [Image(), Image()] // get your images from somewhere
// we are on the main thread where UI operations are ok, so:
startProgressIndicator()
uploadInBackground(images) { success in
// this callback is called on the main thread, so:
stopProgressIndicator()
guard success else { return }
// images uploaded ok, so proceed with functions that depend on
// the upload(s) completing successfully:
function1()
function2()
}
}
Despite running the upload image function in the main queue, the upload image function itself is running operations in a background queue. To fix this, possible strategies would be:
use a completion handler with the image upload, likely the easiest to implement depending on the implementation of the self.uploadImages() function
make the image uploading happen on the main thread, which is likely hard to implement and inadvisable
use a dispatch group, which I personally have less experience with but is an option

Looping through entities which describe what action should be taken on screen after keypresses

Please forgive me if I don't describe this question too well, I am new to programming MacOS apps using Swift. I know the way I'm going about this is probably wrong and I just need someone to tell me the right way.
My main app screen
I have a Core Data application that stores an ordered list of entities called Items. These Items are intended to describe a single step in an activity that describes what should happen on screen. If you know the Mac application QLab each Item is like a single cue in QLab.
I have created an Activity class that is designed to read through each Item to determine the Item type and it's related information. Once the Item type has been determined the Activity class needs to present a View with information related to that particular Item and then wait until the user presses the right arrow key to then proceed to the next Item in the Core Data store where the process repeats until all Items have been read. Each time a new Item is read in the loop, the information on the screen should change after the user presses the right arrow each time.
The problem is that I don't know exactly how the best way of going about this should be programatically speaking. I have the code that retrieves the array of Items as an NSFetchRequest:
let moc = (NSApplication.shared.mainWindow?.contentViewController?.representedObject as! NSPersistentDocument).managedObjectContext!
let fetchRequest : NSFetchRequest = Item.fetchRequest()
do {
let items = try moc.fetch(fetchRequest)
print("Found " + String(items.count) + " items to use in the activity.")
for item in items {
print(item.itemType)
// How do I pause this loop for a user keypress after using data from this Item to display?
}
} catch {
print("Error retrieving Items")
}
I can retrieve the keydown event using NSEvent.addLocalMonitorForEvents(matching: .keyDown) and I'm also able to create View Controllers to display the information on a second screen. I just don't know how I should create the 'main loop', so to speak, so that information is displayed and then the app waits until the user presses a key to proceed...
I can share my project code if more information is needed and many thanks to anyone who can enlighten me... :)
You could try using a NSPageController. In your NSPageController you add a ContainerView which will display the ViewControllers that display information for each item. Each ViewController will need a storyboard identifier, e.g. ViewControllerItem1.
Your NSPageController class must conform to the NSPageControllerDelegate protocol and contains an array of ViewControllers to display.
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
arrangedObjects = ["ViewControllerItem1", "ViewControllerItem2", "...","ViewControllerItemN" ]
}
Note about arrangedObjects from the NSPageController documentation: An array containing the objects displayed in the page controller’s view.
Then you implement NSPageControllers viewControllerForIdentifier to return the ViewController that you currently want to display in the ContainerView.
func pageController(_ pageController: NSPageController, viewControllerForIdentifier identifier: String) -> NSViewController {
switch identifier {
case "ViewControllerItem1":
return mainStoryboard().instantiateController(withIdentifier:"ViewControllerItem1") as? ViewControllerItem1
case "...":
default:
}
}
In your action handler for the key down event you implement.
self.navigateForward(sender) or self.navigateBack(sender)
I also implemented this method but I don't remember whether it was required.
func pageControllerDidEndLiveTransition(_ pageController: NSPageController) {
self.completeTransition()
}

How to force UI Display to update in swift?

I'm trying to get the View Controller to update while I'm in a loop that calls a function that does tons of Label updates. But the update to the screen doesn't happen until I've finished the loop.
Is there a way to force a UI update before continuing? Something like forcing data to be written to a disk.
code for the button to start the loop is something like this:
while (match.currentInnings == currentInnings)
{
playSingleBall()
if (gameover == true)
{
return
}
}
After playSingleBall, I'd like to force a UI update before continuing.
Thanks.
Call it in Dispatch Queue:
Swift 3.x
DispatchQueue.main.async {
updateYourUI()
}
Swift 2.x
dispatch_async(dispatch_get_main_queue()) {
updateYourUI()
}

MBProgressHUD different load styles

I am having some issues to get MBProgressHUDModeDeterminateHorizontalBar style to work
Haven't found much around on Swift.
I've tried so far to create an object passing the MBProgressHUDModeDeterminateHorizontalBar as type or attribute it as a mode to an existing HUB object or add an int to the mode... but nothing seems to work.
let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
spinningActivity.labelText = "Loading"
spinningActivity.detailsLabelText = "Please got get some coffee"
You need to change MBProgressHUD mode. See code bellow.
spinningActivity.mode = .DeterminateHorizontalBar
And update your loading progress:
spinningActivity.progress = /*Your loading progress*/
Hope that help!