I am testing an app which samples data. Part of the test I am setting up requires a few data points to be stored. I would like to do this by having XCTest execute the acquisition method followed by a sleep() function and yet another call to the acquisition method.
Though there are methods to wait for an expectation with timeout, there doesn't seem to be a simple wait()/sleep() method that simply pauses execution for specified amount of time. Any idea how I can do this using Xcode 6 and Swift?
You can use NSTimer to space out your data calls instead of locking up the app with sleep
func dataCall(timer : NSTimer) {
// get data
}
let myTimer : NSTimer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: Selector("dataCall:"), userInfo: nil, repeats: false)
and of course you can alter those parameters to your liking and needs.
Related
I am writing an OS X app that includes a generic stopwatch timer. I'm using NSTimer. I'd like the user to be able to start the timer and come back to it after a long time (say, 30 minutes), and the timer would still be running. The problem is that my timer does not continue running while the computer is closed or asleep, and I don't want to keep my computer open and on for really long periods of time. There are several threads about this problem concerning iOS apps, but none (at least that I've found) pertaining to OS X. Does anyone know of a workaround for this issue? As an example, I'm trying to mimic the "Stopwatch" functionality of the "Clock" app that comes with iOS, except with a laptop instead of a phone. The stopwatch in the "clock" app will continue running even when the phone is off for extended periods of time.
The way I figured out to do this was not to actually run the NSTimer in the background, but rather to find out how much time had elapsed between when the app goes into the background and when it comes back into focus. Using the delegate methods applicationWillResignActive: and applicationWillBecomeActive: of NSApplicationDelegate:
let timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(self), userInfo: nil, repeats: true)
var resignDate: NSDate?
var stopwatch = 0
func update() {
stopwatch += 1
}
func applicationWillResignActive(notification: NSNotification) {
timer.invalidate()
resignDate = NSDate() // save current time
}
func applicationWillBecomeActive(notification: NSNotification) {
if resignDate != nil {
let timeSinceResign = NSDate().timeIntervalSinceDate(resignDate!))
stopwatch += Int(timeSinceResign)
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(self), userInfo: nil, repeats: true)
resignDate = nil
}
}
applicationWillResignActive: will get called every time the app goes out of focus. When this happens, I save the current date (NSDate()) in a variable called resignDate. Then, when the application is reactivated (after who knows how long; it doesn't matter) applicationWillBecomeActive: is called. Then, I take another NSDate value that is the current time, and I find the amount of time between the current time and resignDate. After adding this amount of time to my time value, I can revalidate and the NSTimer so it keeps going.
I have an app that uses 3 functions which use NSTimer which are called consecutively or one after the other. I would like for these functions to be repeated for x amount of times because I have an #IBOutlet called repsField which creates a value that is stored in the global variable repetitionswhich is by default set to 0 until a user changes this value using the #IBOutlet.
Basically, I'd like to multiply the amount of times that the functions are called by the global variable repetitions. How can I do this?
Screenshot:
Here's an example of one of the timers...
func start1() {
if timerRunning==false{ // Timer will start
timer=NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("Counting1"), userInfo: nil, repeats: true)
timerRunning=true
}
}
func Counting1(){
timerCount+=1 timerLabel.text="\(timerCount) secs"
if timerRunning==true && timerCount >= timerMaximum {
stop()
intervalAlert()
start2()
}
}
Please get back to me as soon as possible
Use a for loop:
for count in 1...repetitions {
// do stuff
}
Check out: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ControlFlow.html
I'm trying to test a little proof-of-concept command line app prior to integrating it into a larger app. What I'm trying to do is download some data using NSURLSession using this example. However it appears that if I use the examples given in a simple OS X command line app then the app exits prior to the data being retrieved.
How can I download data from a stand-alone command line app using NSURLSession? What I've read about is using NSRunLoop however I've not yet found a clear example in Swift so if NSRunLoop is actually the way to go then any examples would be appreciated.
Any other strategies for downloading data from a URL for a Swift command line app is also welcome (infinite while loop?).
You can use a semaphore to block the current thread and wait for your URL session to finish.
Create the semaphore, kick off your URL session, then wait on the semaphore. From your URL session completion callback, signal the semaphore.
You could use a global flag (declare a volatile boolean variable) and poll that from a while loop, but that is less optimal. For one thing, you're burning CPU cycles unnecessarily.
Here's a quick example I did using a playground:
import Foundation
var sema = DispatchSemaphore( value: 0 )
class Delegate : NSObject, URLSessionDataDelegate
{
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
{
print("got data \(String(data: data, encoding: .utf8 ) ?? "<empty>")");
sema.signal()
}
}
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: Delegate(), delegateQueue: nil )
guard let url = URL( string:"http://apple.com" ) else { fatalError("Could not create URL object") }
session.dataTask( with: url ).resume()
sema.wait()
Try this
let sema = DispatchSemaphore( value: 0)
let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_November_2010-1a.jpg")!;
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
print("after image is downloaded");
sema.signal(); // signals the process to continue
};
task.resume();
sema.wait(); // sets the process to wait
For proof of concept(s) or tryouts/testing purposes, you can simplify asynchronous complexity by hard coding some timeout period until your stuff finishes. (see notes below)
SWIFT 5
//...your magic here
// add a little 🤓iness to make it fun at least...
RunLoop.main.run(until: Date() + 0x10) //oh boi, default init && hex craze 🤗
// yeah, 16 seconds timeout
// or even worse (!)
RunLoop.main.run(until: .distantFuture)
SWIFT 3 or earlier
//...your stuff here
RunLoop.main.run(until: Date(timeIntervalSinceNow: 15)) //will execute things on main loop for 15 seconds
NOTES :
DO NOT USE THIS IN PRODUCTION
respect the first rule
This is very quick and dirty way to overcome serious concerns of parallelism. Explore better and more complex solutions described in other answers of this question.
My app uses multiple threads of NSTimer Object.
Within the one function (called randomly at random times, not a fixed delay) I want it to pause the whole app, pause the threads for 1 second only. I have the following code:
[self performSelector:#selector(subscribe) withObject:self afterDelay:3.0 ];
Which is objective C, and I tried translating it into Swift like this:
self.performSelector(Selector:changeColourOfPage(), withObject: self, afterDelay: 1.0)
But I am getting the error Missing argument for parameter 'waitUntilDone' in call and when I put that in, it says it wants the argument modes but when I put that in it says Extra argument modes.
I cannot figure out how to pause the app and all it's threads for a couple of seconds, and then carry on like normal?
Any ideas?
The performSelector methods aren't available in Swift. You can get the delay functionality by using dispatch_after.
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC * 1))
dispatch_after(delayTime, dispatch_get_main_queue()){
changeColourOfPage()
}
Another way in Swift 3.1
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
changeColourOfPage()
}
You can substitute other units like .milliseconds(1000) or .microseconds(1_000_000) or .nanoseconds(1_000_000_000) for the time interval.
Sorry to answer an old question, but just came along a better way to do this -
import Darwin //Put this line at the beginning of your file
func pauseForAMoment() {
sleep(1)
changeColorOfPage()
}
Before Swift, in Objective-C I would swizzle or hook methods in a class using <objc/runtime.h>.
If anyone has any info on the topic of modifying Swift's runtime and hooking functions like CydiaSubstrate and other libraries that helped in this area, please inform me.
I've succeed with method swizzling in Swift. This example shows how to hook description method on NSDictionary
My implementation:
extension NSDictionary {
func myDescription() -> String!{
println("Description hooked")
return "Hooooked " + myDescription();
}
}
Swizzling code:
func swizzleEmAll() {
var dict:NSDictionary = ["SuperSecret": kSecValueRef]
var method: Method = class_getInstanceMethod(object_getClass(dict), Selector.convertFromStringLiteral("description"))
println(dict.description) // Check original description
var swizzledMethod: Method = class_getInstanceMethod(object_getClass(dict), Selector.convertFromStringLiteral("myDescription"))
method_exchangeImplementations(method, swizzledMethod)
println(dict.description) //Check that swizzling works
}
Edited:
This code will work for any custom Swift class that inherits from NSObject (but will not work for classes that don't.) More examples - https://github.com/mbazaliy/MBSwizzler
You would likely be able to swizzle swift-generated classes that inherit from Objective-C classes with no problem, since they appear to use dynamic method dispatch all the time. You may be able to swizzle methods of swift-defined classes that exist in the Objective-C runtime by virtue of being passed across the bridge, but the Objective-C side methods are likely to just be proxies back across the bridge to the swift-side runtime, so it's not clear that it'd be particularly helpful to swizzle them.
"Pure" swift method calls do not appear to be dispatched dynamically via anything like objc_msgSend and it appears (from brief experimentation) that the type safety of swift is implemented at compile time, and that much of the actual type information is absent (i.e. gone) at runtime for non-class types (both of which likely contribute to the purported speed advantages of swift.)
For these reasons, I expect that meaningfully swizzling swift-only methods will be significantly harder than swizzling Objective-C methods, and will probably look a lot more like mach_override than Objective-C method swizzling.
I'm answering this question more than one year later because none of the other answers provide the definitive set of requirements for method swizzling for every kind of class.
What is described by other, while it will work flawlessly for extensions to foundation/uikit classes (like NSDictionary), will simply never work for your own Swift classes.
As described here, there is an additional requirement for method swizzling other than extending NSObject in your custom class.
The swift method you want to swizzle must be marked dynamic.
If you don't mark it, the runtime will simply continue to call the original method instead of the swizzled one, even if the method pointers appear to have been swapped correctly.
Update:
I've expanded this answer in a blog post.
I had a Xcode 7 iOS project written in Swift 2, using Cocoapods. In a specific Cocoapod, with Objective-C source, I wanted to override a short method, without forking the pod. Writing a Swift extension wouldn't work in my case.
For using method swizzling, I created a new Objective-C class in my main bundle with the method I wanted to replace/inject into the cocoapod. (Also added the bridging header)
Using mbazaliy 's solution on stackflow, I put my code similar to this into the didFinishLaunchingWithOptions in my Appdelegate:
let mySelector: Selector = "nameOfMethodToReplace"
let method: Method = class_getInstanceMethod(SomeClassInAPod.self, mySelector)
let swizzledMethod: Method = class_getInstanceMethod(SomeOtherClass.self, mySelector)
method_exchangeImplementations(method, swizzledMethod)
This worked perfectly. The difference between #mbazaliy 's code is that I didn't need to create an instance of the SomeClassInAPod class first, which in my case would have been impossible.
Note: I put the code in the Appdelegate because every other time the code runs, it exchanges the method for the original - it should only run one time.
I also needed to copy some assets that were referenced in the Pod's bundle to the main bundle.
I wouldn't do it that way, I think closures provide the answers (as they give you a chance to intercept, evaluate, and forward the invocation of the function, additionally it will be easy to extend when and if we have reflection.
http://www.swift-studies.com/blog/2014/7/13/method-swizzling-in-swift
I would like to extend the great answer provided by mbazaliy.
Another way of doing swizzling in Swift is by providing an implementation using an Objective-C block.
e.g. to replace descriptionmethod on class NSString we can write:
let originalMethod = class_getInstanceMethod(NSString.self, "description")
let impBlock : #objc_block () -> NSString =
{ () in return "Bit of a hack job!" }
let newMethodImp = imp_implementationWithBlock(unsafeBitCast(impBlock, AnyObject.self))
method_setImplementation(originalMethod, newMethodImp)
This works as of Swift 1.1.
A safe, easy, powerful and efficient hook framework for iOS (Support Swift and Objective-C). https://github.com/623637646/SwiftHook
For example, this is your class
class MyObject {
#objc dynamic func noArgsNoReturnFunc() {
}
#objc dynamic func sumFunc(a: Int, b: Int) -> Int {
return a + b
}
#objc dynamic class func classMethodNoArgsNoReturnFunc() {
}
}
The key words of methods #objc and dynamic are necessary
The class doesn't have to inherit from NSObject. If the class is written by Objective-C, Just hook it without any more effort
Perform the hook closure before executing specified instance's method.
let object = MyObject()
let token = try? hookBefore(object: object, selector: #selector(MyObject.noArgsNoReturnFunc)) {
// run your code
print("hooked!")
}
object.noArgsNoReturnFunc()
token?.cancelHook() // cancel the hook
Perform the hook closure after executing specified instance's method. And get the parameters.
let object = MyObject()
let token = try? hookAfter(object: object, selector: #selector(MyObject.sumFunc(a:b:)), closure: { a, b in
// get the arguments of the function
print("arg1 is \(a)") // arg1 is 3
print("arg2 is \(b)") // arg2 is 4
} as #convention(block) (Int, Int) -> Void)
_ = object.sumFunc(a: 3, b: 4)
token?.cancelHook() // cancel the hook
The key word #convention(block) is necessary
For hook at before and after. The closure's args have to be empty or the same as method. The return type has to be void
Totally override the mehtod for specified instance. You can call original with the same parameters or different parameters. Don't even call the original method if you want.
let object = MyObject()
let token = try? hookInstead(object: object, selector: #selector(MyObject.sumFunc(a:b:)), closure: { original, a, b in
// get the arguments of the function
print("arg1 is \(a)") // arg1 is 3
print("arg2 is \(b)") // arg2 is 4
// run original function
let result = original(a, b) // Or change the parameters: let result = original(-1, -2)
print("original result is \(result)") // result = 7
return 9
} as #convention(block) ((Int, Int) -> Int, Int, Int) -> Int)
let result = object.sumFunc(a: 3, b: 4) // result
print("hooked result is \(result)") // result = 9
token?.cancelHook() // cancel the hook
For hook with instead. The closure's first argument has to be a closure which has the same types with the method. The rest args and return type have to be the same as the method.
Perform the hook closure before executing the method of all instances of the class.
let token = try? hookBefore(targetClass: MyObject.self, selector: #selector(MyObject.noArgsNoReturnFunc)) {
// run your code
print("hooked!")
}
MyObject().noArgsNoReturnFunc()
token?.cancelHook() // cancel the hook
Perform the hook closure before executing the class method.
let token = try? hookClassMethodBefore(targetClass: MyObject.self, selector: #selector(MyObject.classMethodNoArgsNoReturnFunc)) {
// run your code
print("hooked!")
}
MyObject.classMethodNoArgsNoReturnFunc()
token?.cancelHook() // cancel the hook
After spending some time on it... Wake up this morning.... beta 6 is out and
Problem Fixed in beta6!
From release notes
"Dynamic dispatch can now call overrides of methods and properties introduced in class extensions, fixing a regression introduced in Xcode 6 beta 5. (17985819)!"