I'm trying to understand IOKit and how it allows me to access serial ports in a Swift program.
The class I'm manipulating at the moment is as follows:
import Foundation
import Cocoa
import IOKit.serial.IOSerialKeys
class Serial {
init() {
}
#IBOutlet var serialListPullDown : NSPopUpButton!
func refreshSerialList(defaultprompt: String) {
// remove everything from the pull down list
serialListPullDown?.removeAllItems()
// ask for all the serial ports
IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOSerialBSDServiceValue), io_iterator_t)
}
}
Based on what I've read I think I've setup IOServiceMatchingServices correctly but I'm getting several errors such as "Expected member name or constructor call after type name" and "'o_iterator_t.Type' is not convertible to 'UnsafeMutualPointer'"
What does this mean?
A few different issues going on in there -- let's get your imports squared away first. It looks like you need these two:
import IOKit
import IOKit.serial
For the parameters, it'll be easier to see what we're working with if we define them as local variables, like so:
// this one's easy, just grabbing a constant from IOKit.serial
let masterPort: mach_port_t = kIOMasterPortDefault
// here we get back an Unmanaged<CFMutableDictionary> and need to convert it to
// a CFDictionary using takeRetainedValue()
let classesToMatch: CFDictionary = IOServiceMatching(kIOSerialBSDServiceValue).takeRetainedValue()
// the iterator that will contain the results of IOServiceGetMatchingServices
var matchingServices: io_iterator_t = 0
And lastly, you call the method:
// note that the last parameter is an UnsafeMutablePointer<io_iterator_t>
// so we need to prefix matchingServices with an ampersand (&)
let kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, &matchingServices)
if kernResult == KERN_SUCCESS {
// success
} else {
// error
}
This feels pretty near the edge of what Swift can handle right now -- definitely read these two pages well before going further:
Interacting with C APIs (Pointers section)
Working with Cocoa Data Types (Unmanaged Objects section)
Lastly, make sure you can get into the converted Swift declarations for the IOKit framework. There are a lot of useful comments and you'll be able to see which parameters and return values are unmanaged or pointers (since I don't think this framework's official documentation has been updated yet).
Related
The Problem
I am trying to get the new AUParameterTree and AUParameter's mechanism working in my Audio Unit V3 test project. The problem is that when I gain a reference to it from the Host App and change its value, the Audio Unit extension's parameter doesn't appear to change.
Here is my approach.
I'm using the new Audio Unit V3 API. I've created an AUParameter in my AUAudioUnit's initWithComponentDescription:
Creating the Parameter
AUParameter *param1 = [AUParameterTree createParameterWithIdentifier:#"frequency"
name:#"Frequency"
address:frequencyAddress
min:500
max:5000
unit:kAudioUnitParameterUnit_Hertz
unitName:nil
flags:0
valueStrings:nil
dependentParameters:nil];
Set a default value..
param1.value = 0.5;
some of the arguments to the Parameter constructor come from...
Some State
I have defined the address as a global constants:
const AudioUnitParameterID frequencyAddress = 0;
And a local variable for an AUValue:
AUValue frequency = 1;
Keep in mind at this point I'm just following the three example projects that use Audio Unit V3 on the entire internet. I find it difficult to piece together how this entire AU parameter dance should go only from reading the docs.
Rendering with the parameter
now when it comes to using the AUValue associated with the AUParameter "param1", (I assume thats how it works?)..
I am then capturing this AUValue ( the local variable which I'm unclear on how it is associated with the actual AUParameter ) .. in my Audio Unit rendering block:
- (AUInternalRenderBlock)internalRenderBlock {
AUValue * param1Capture = &frequency;
return ^AUAudioUnitStatus(AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, NSInteger outputBusNumber, AudioBufferList *outputData, const AURenderEvent *realtimeEventListHead, AURenderPullInputBlock pullInputBlock) {
// use parameter value
someValue = *param1Capture;
// more dsp stuff..
Controlling Parameter from Host App
This is where the problem arises.
I declare a local reference to an AUParameter:
#interface ViewController (){
AudioEngine *_audioEngine;
AUParameter * _param1;
}
and when my Audio Engine class instantiates my AUAudioUnit it passes it to me:
[_audioEngine setupAUWithComponentDescription:desc andCompletion:^(AUAudioUnit * unit){
_param1 = [unit.parameterTree valueForKey:#"frequency"];
}];
no effect?
Now when I say:
[_param1 setValue: 1000];
The captured AUValue in my rendering block remains the same!
I've either overlooked a bug, a mindless type (I may have introduced a type in this write up of my problem so keep that in mind), or I have fundamentally misunderstood this mechanism.
If I need to provide more context for this problem I can easily push the project to Github.
Thanks in advance.
The problem turned out to have nothing to do with Core Audio and everything to do with a basic language level mistake.
frequency was declared at a file level scope like this:
AUValue frequency = 1;
#implementation MyAudioUnit
#end
My understanding is that frequency is now bound to file scope and not instance scope. Therefore repeated setting of it on different instances was simply overwriting the previous value. Hence, the last assignment was the frequency which would be rendered.
Since I am fairly new to Swift programming on OSX, this question may contain several points that needs clarification.
I have a method which iterates over all subviews of a given NSView instance. For this, I get the array of subviews which is of type [AnyObject] and process one element at a time.
At some point I would like to access the identifier property of each instance. This property is implemented from a protocol in NSView named NSUserInterfaceItemIdentification, which type is given in the documentation as (optional) String?. In order to get that identifier I would have written
var view : NSView = subview as NSView;
var viewIdent : String = view.identifier!;
The second line is marked by the compiler with an error stating that identifier is not of an optional type, but instead of type String, and hence the post-fix operator ! cannot be applied.
Removing this operator compiles fine, but leads to a runtime error EXC_BAD_ACCESS (code=1, address=0x0) because identifier seems to be nil for some NSButton instance.
I cannot even test for this property, because the compiler gives me a String is not convertible to UInt8 while I try
if (view.identifier != nil) {viewIdent = view.identifier;}
My questions are
Is the documentation wrong? I.g. the property identifier is not optional?
How can I ship around this problem and get code that runs robust?
If the documentation states that view.identifier is an Optional, it means it can be nil. So it's not a surprise that for some button instances it is indeed nil for you.
Force unwrapping this element that can be nil will lead your app to crash, you can use safe unwrapping instead:
if let viewIdent = view.identifier {
// do something with viewIdent
} else {
// view.identifier was nil
}
You can easily check the type of an element in Xcode: click on the element while holding the ALT key. It will reveal a popup with informations, including the type. You can verify there that your element is an Optional or not.
Tip: you can safe unwrap several items on one line, it's rather convenient:
if let view = subview as? NSView, viewIdent = view.identifier {
// you can do something here with `viewIdent` because `view` and `view.identifier` were both not nil
} else {
// `view` or `view.identifier` was nil, handle the error here
}
EDIT:
You have to remove this line of yours before using my example:
var viewIdent : String = view.identifier!
Because if you keep this line before my examples, it won't work because you transform what was an Optional in a non-Optional by adding this exclamation mark.
Also it forces casting to a String, but maybe your identifier is an Int instead, so you shouldn't use this kind of declaration but prefer if let ... to safe unwrap and cast the value.
EDIT2:
You say my example doesn't compile... I test every answer I make on SO. I tested this one in a Playground before answering, here's a screenshot:
Also, after checking it, I confirm that the identifier is an Optional String, that's the type given by Xcode when using ALT+CLICK on the property. The documentation is right.
So if it's different for you, it means you have a different problem unrelated to this one; but my answer for this precise question remains the same.
I am trying to trap keypresses using a CGEventTapCreate etc in Swift. I want to do this so that when my toddler is using a program the Mac, I can limit which keys do something. I appreciate that I need to enable assistive technology to get CGEventTap to work
I am having trouble understanding what I need to do in Swift to get the final parameter in the call. Essentially, I do not understand part of the documentation at quartz event documentation
Specifically the final parameter which is described by
refcon: A pointer to user-defined data. This pointer is passed into
the callback function specified in the callback parameter.
Here is my code missing the final parameter from the call
#IBAction func interceptKeyboard(sender: NSButton) {
CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, CGEventMask((kCGEventKeyDown) | (kCGEventKeyUp)), MyCallBack: kCGHIDEventTap, )
}
func MyCallBack(myLocation:CGEventTapLocation) -> Void{
//do Nowt
}
Bit of a while ago, but I think when you look at the type of CGEventTapCallback, you see that it is a CFunctionPointer:
typealias CGEventTapCallBack = CFunctionPointer<((CGEventTapProxy,
CGEventType, CGEvent!, UnsafeMutablePointer<Void>) -> Unmanaged<CGEvent>!)>
At the moment you can't create these in Swift, so you have to dip into objective-c, create a function there, which can then call an equivalent function in Swift, see here:
Objective-C Wrapper for CFunctionPointer to a Swift Closure
I ended up writing the whole of this stuff in Objective-C...
I've got some code that runs a fairly complex algorithm. I want to put together a fairly simple UI that will allow me to monitor the values of the various variables in the algorithm in some graphical ways -- think of it like a dashboard of sorts.
So, for simplicity's sake, let's say I have an algorithm like what follows. It searches a vector of values for the two values that most closely sum to a target value:
import Foundation
class algorithm {
var numbers = [Double]()
let numberOfRandoms = 1000
dynamic var a: String
dynamic var b: String
init () {
// Load initial vector with some random numbers between 0 and 1
for _ in 1...numberOfRandoms {
numbers.append(Double(arc4random()) / Double(UINT32_MAX))
}
a = " "
b = " "
}
func findTheTwoNumbersThatAddUpTheClosestToTarget(target: Double) {
//Initializing this to a very large value
var currentBestSum = 1000.0
//Begin brute force search for the optimal solution
for i in 0...numbers.count-2 {
for j in i+1...numbers.count-1 {
//Check to see if the current candidate exceeds the best solution
if abs(numbers[i] + numbers[j] - target) < currentBestSum {
//If it does, store the new champion
a = String(i)
b = String(j)
//And reset the current top score to match
currentBestSum = abs(numbers[i] + numbers[j]-target)
}
}
}
}
}
Now, this is just a simple (and silly) example, but it suits these purposes. I basically want to create a simple UI that displays the important values in the process as it runs (dynamically).
In this example, let's say that I just want to display two labels that contain the index values of the two leaders as the algorithm executes.
I created the labels in the storyboard.
Then, I created IBOutlets in the ViewController (Actually, storyboards did it for me when I Ctrl-dragged):
class ViewController: NSViewController {
#IBOutlet weak var a: NSTextField!
#IBOutlet weak var b: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
Then, I ctrl-dragged the labels to the a and b in the algorithm class to create the bindings.
Finally, I create an class variable in the view controller and instantiate it in the viewDidLoad method. This doesn't seem like the right thing to do -- maybe it is. Seems like you would want to keep separate your interface and data...
The labels do, in fact, show up -- but they never show any values of a and b. They just show the default text.
Not sure what I'm doing wrong.
Help!?
P.S., in response to Anthony Kong, I do recognize that I could manually synchronize all the view elements in the code, but I thought the whole point of using bindings was to avoid having to do this manual synchronization. I just can't figure out how to set it up.
Without commenting on your specific code I think I have experienced (and solved) the problem you describe. I was able to write an app that had two targets, one NIB-based and one Storyboard-based. As much as I was able I duplicated the code in each and shared the common data instance that I was trying to display in a TableView. The NIB-based app worked using the stock Cocoa Bindings that I set in IB. But the Storyboard-based app did not, the array controller did not see the data.
My solution was simply to add the binding for contentArray programmatically in viewDidLoad. The one line that fixed it for me is:
ac.bind("contentArray", toObject: cd, withKeyPath: "people", options: nil)
ac is the IBOutlet for the ArrayController in the Storyboard. cd is the class instance that contains the people array.
This is using XCode 6.2 (6C107a) which is Beta 3 I think.
This was the only binding that I had to set myself, the TableView to ArrayController (arrangedObjects) and TableViewCell to TableView (objectValue) didn't need any tweaking.
There are several problems with your code
1) In your code,
func applicationDidFinishLaunching(aNotification: NSNotification?) {
// Insert code here to initialize your application
var test = algorithm()
test.findTheTwoNumbersThatAddUpTheClosestToTarget(0.5)
}
The variable test goes out of scope when the function exits. Based on the wording of your question, you are expecting it to be a long running process. So this will not do what you want.
You should
a) Add test as class variable to the ViewController class
b) instantiate the variable in viewDidLoad method.
2) In your algorithm it does not actually provide any feedback to the labels. Maybe you think because the class has the ivar a and b so they are hooked to the IBOutlet by the same names. But of course it is not the case. And you do not need the keyword dynamic too.
What you should do is:
a) provide a method in the View Controller class to update the labels. It will serve as a callback function to be used by algorithm class to feedback the calculation result.
It may look like this:
func update_value_callback(vala: String, valb: String) {
a.text = vala; // updating the label here
b.text = valb;
}
b) make the algorithm class calls the callback function e.g.
func findTheTwoNumbersThatAddUpTheClosestToTarget(target: Double, viewController: ViewController) {
// do your stuff
...
// execute the callback
viewController.update_value_callback(a, b)
}
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)!"