AudioPlaybackComplete use of undeclared identifier self calling methods - iphone

I'm getting use of undeclared identifier self error when I'm calling any method from AudioPlaybackComplete. Any of you know why or how can I fixed?
static void AudioPlaybackComplete(SystemSoundID ssID, void *data)
{
[self doSomething]; /// error use of undeclared identifier self
}

You will need to pass the object (the one you want refered to by self) by using the data pointer *data . Either point at the object directly (then cast it back to an object of the proper class/type for use), or pass in the object as an element of a C struct pointed to by *data.
Objective C method calls do this as well, but pass and set self automatically and hidden from view by the compiler, instead of explicitly by having to code it. Since you are using a C function, you will have to code this yourself.

You're calling self from within a static function - self refers to a specific instance of the class.

Related

Why can't I access the delegate property of my view controller in my Swift project?

I have a view controller called ServiceDetailController with a delegate property shown below:
weak var delegate: ServiceDetailControllerDelegate?
and I am trying to initialize it with a delegate instance in the next view controller in the navigation stack using:
for controller in navigationController!.viewControllers as Array {
if controller.isKind(of: ServiceDetailController.self) {
controller.delegate = self
}
}
But Xcode is giving me an error
Value of type 'UIViewController" has no member 'delegate'.
Any help gratefully received.
Your code confirms that a controller is of type ServiceDetailController before it runs the code after your if statement, but inside the if statement, the variable controller is still of type ViewController. (Actually, since you cast navigationController!.viewControllers to Array, controller is probably type Any. I'd get rid of that as Array bit from your for loop. It does more harm than good.)
You need to cast the variable to the right type in order to access properties of your specific subclass. Change your code as follows:
for controller in navigationController!.viewControllers {
if let sdc = controller as? ServiceDetailController {
sdc.delegate = self
}
}
The if let syntax is called "optional binding", and creates a new variable inside the braces of the if statement that is valid if the if let succeeds. In our case we're using as? to try to cast the view controller to type ServiceDetailController. If the cast succeeds, the code inside the braces is executed, and has access to the variable sdc,which is of type ServiceDetailController.

Swift compiler cannot distinguish two initializers

Basically, I have a class called UserData and multiple initializers for it. In particular, I have a copy initializer which looks like:
init (_ origin: UserData){
// copy over everything
}
And another initializer which is used when I need to read the data from a file:
convenience init (Read _: Bool) {
// read stuff and call another initializer
}
Then I always got a compiler error saying cannot convert Bool to UserData whenever I tried to do var something = UserData(true).
I tried adding label, but compiler said extroneous label since there is only one parameter. I could make a workaround by adding another random parameter to the second initializer. But why is the compiler always trying to interpret the call to something does not match the type while there is another that matches the type?
Swift has no problem distinguishing two initializers with one parameter. The error is because of how the second one is defined. It should be:
convenience init (_ read: Bool) {
// read stuff and call another initializer
}

Swift semantics calling a method on a (nullable) weak reference using the ?. operator

Back in objective-C with ARC, this wasn't safe to do:
MyClass* someObject = ...
__weak MyClass* weakSomeObject = someObject;
doSomething(^{
[weakSomeObject someMethod];
});
Why? because simply calling a method doesn't cause ARC to retain the object, and thus the someObject instance might be released and dealloced in the middle of the execution of someMethod
Bringing this forward into swift, it translates as follows:
let someObject: MyClass = ...
doSomething { [weak someObject]
someObject?.someMethod()
}
My question is, what are the semantics of the ?. operator in swift regarding ARC, and is it safe to use with weak reference method calls?
I can imagine the swift compiler translating the above code into something like this:
let someObject: MyClass = ...
doSomething { [weak someObject]
if let tmp = someObject {
tmp.someMethod()
}
}
If it did that, then it would indeed be safe, as tmp is a strong reference and thus would cause ARC to retain the object across the duration of the call to someMethod
However, I could also imagine it translating into something without an ARC retain for performance reasons or whatever.
Does anyone know what it actually does, and is there a specification or document that makes this explicit?
Bullet points to get first:
closures capture context.
if let, guard etc only checks if optional contains actual value but doesn't capture it's context.
Now about ?. It's optional chaining, if object on which method is called is nil, it won't call method as well as fail full chain(if you follow up return value from method with another method call or else).
About weak and unowned references to used objects inside closure:
weak doesn't create strong reference to object, so it makes it optional because object may not be there when it gets called
unowned as well as weak doesn't create strong reference, however object won't be optional, so you must guarantee that closure won't outlive object it uses, because you will get crash referencing object that isn't there.
Hope it helps.
Short answer is yes, it is safe. Longer explanation and link follow:
Methods defined for a type in Swift are curried functions like this:
class MyClass {
func doSomething() {
// I can access self in here
}
}
print(type(of: MyClass.doSomething)) //(MyClass) -> () -> ()
In other words, the function defined on the type is curried such that it must first be passed a reference to what will be self, which is strongly captured in the returned partially applied function (()->())
When you call the method on an instance of MyClass (not the type itself), it automatically does the initial partial application of passing in that instance of self which is then captured strongly by the resulting closure that is actually invoked.
So the type of MyClass.doSomething is (MyClass) -> () -> (), and the type of MyClass().doSomething is () -> (), where the initial MyClass reference is already captured inside the () -> ().
Given the below code:
weak var test: MyClass? = MyClass()
test?.doSomething()
On line 2, a couple things happen. First, if test is non-nil, it will be passed to the the method implementation on the type MyClass and captured by the MyClass type's curried function (MyClass) -> () ->(). This captured reference is the "self" that can be used inside that instance method.
Then, the resulting partially applied function of type ()->() is invoked, and the strong reference / capture of self from above is released once the function executes.
So, the answer is then yes, it is safe to call instance methods on a weak reference, because the instance method actually strongly captures the instance up until and while it is executing.
This post discusses how instance methods in Swift are curried in more detail, and links to the initial dev forum source of the information.
https://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/
UPDATE:
Some additional interesting and in-depth articles on this mechanism:
http://rosslebeau.com/2016/sneaky-reference-cycles-swift-instance-methods
https://www.klundberg.com/blog/capturing-objects-weakly-in-instance-method-references-in-swift/

AudioToolbox, C-function pointers, and Swift

I'm working, tentatively, with the AudioToolbox API using Swift 2.0 and Xcode 7b6. The API uses a lot of c-language constructs, including function pointers. This is my first time working with commands like withUnsafeMutablePointer and unsafeBitCast. I am looking for a reality check to make sure that I am not way off base in what I am doing.
For example, to open a file stream, you use the following function:
func AudioFileStreamOpen(
_ inClientData: UnsafeMutablePointer<Void>
, _ inPropertyListenerProc: AudioFileStream_PropertyListenerProc
, _ inPacketsProc: AudioFileStream_PacketsProc
, _ inFileTypeHint: AudioFileTypeID
, _ outAudioFileStream: UnsafeMutablePointer<AudioFileStreamID>) -> OSStatus
Just the type signature of the function makes me start to sweat.
At any rate, the inClientData parameter needs to be an UnsafeMutablePointer<Void>, and the pointer will point to an instance of the same class I am working in. In other words, it needs to be a pointer to self. My approach is to call the function using withUnsafeMutablePointer like this:
var proxy = self
let status = withUnsafeMutablePointer(&proxy) {
AudioFileStreamOpen($0, AudioFileStreamPropertyListener
, AudioFileStreamPacketsListener, 0, &audioFileStreamID)
}
My first question is whether or not I'm using withUnsafeMutablePointer correctly here. I wasn't sure how to get a pointer to self - just writing &self doesn't work, because self is immutable. So I declared proxy as a variable and passed a reference to that, instead. I don't know if this will work or not, but it was the best idea I came up with.
Next, AudioFileStreamPropertyListener and AudioFileStreamPacketsListener are C callback functions. They each get passed the pointer to self that I created using withUnsafeMutablePointer in AudioFileStreamOpen. The pointer is passed in as an UnsafeMutablePointer<Void>, and I need to cast it back to the type of my class (AudioFileStream). To do that, I believe I need to use unsafeBitCast. For example, here is AudioFileStreamPropertyListener:
let AudioFileStreamPropertyListener: AudioFileStream_PropertyListenerProc
= { inClientData, inAudioFileStreamID, inPropertyID, ioFlags in
let audioFileStream = unsafeBitCast(inClientData, AudioFileStream.self)
audioFileStream.didChangeProperty(inPropertyID, flags: ioFlags)
}
That compiles fine, but again I'm not sure if I'm using unsafeBitCast correctly, or if that is even the correct function to be using in this kind of situation. So, is unsafeBitCast the correct way to take an UnsafeMutablePointer<Void> and cast it to a type that you can actually use inside of a C function pointer?
It's interesting that the inClientData "context" param is bridged as UnsafeMutablePointer, since I doubt the AudioToolbox APIs will modify your data. It seems it would be more appropriate if they'd used COpaquePointer. Might want to file a bug.
I think your use of withUnsafeMutablePointer is wrong. The pointer ($0) will be the address of the variable proxy, not the address of your instance. (You could say $0.memory = [a new instance] to change it out for a different instance, for example. This is a bit confusing because its type is UnsafeMutablePointer<MyClass> — and in Swift, the class type is itself a pointer/reference type.)
I was going to recommend you use Unmanaged / COpaquePointer, but I tested it, and realized this does exactly the same thing as unsafeAddressOf(self)!
These are equivalent:
let data = UnsafeMutablePointer<Void>(Unmanaged.passUnretained(self).toOpaque())
let data = unsafeAddressOf(self)
And these are equivalent:
let obj = Unmanaged<MyClass>.fromOpaque(COpaquePointer(data)).takeUnretainedValue()
let obj = unsafeBitCast(data, MyClass.self)
While the Unmanaged approach makes logical sense, I think you can see why it might be prefereable to use unsafeAddressOf/unsafeBitCast :-)
Or, you might consider an extension on Unmanaged for your own convenience:
extension Unmanaged
{
func toVoidPointer() -> UnsafeMutablePointer<Void> {
return UnsafeMutablePointer<Void>(toOpaque())
}
static func fromVoidPointer(value: UnsafeMutablePointer<Void>) -> Unmanaged<Instance> {
return fromOpaque(COpaquePointer(value))
}
}
Then you can use:
let data = Unmanaged.passUnretained(self).toVoidPointer()
let obj = Unmanaged<MyClass>.fromVoidPointer(data).takeUnretainedValue()
Of course, you will need to ensure that your object is being retained for the duration that you expect it to be valid in callbacks. You could use passRetained, but I would recommend having your top-level controller hold onto it.
See some related discussion at https://forums.developer.apple.com/thread/5134#15725.

Class instance variable initialization order?

Currently, I am seeing something strange behavior.
class DataManager1
{
let THE_ID = "SOME_ID_STRING"
let _con1 = CKContainer(identifier: THE_ID) // error
// error: 'DataManager1.Type' does not have a member named 'THE_ID'
}
class DataManager2
{
let THE_ID = "SOME_ID_STRING"
let _con1:CKContainer?
init()
{
_con1 = CKContainer(identifier: THE_ID) // no error.
}
}
In C++ we have a defined initialization order between instance member variables. I expected something similar, but actually I couldn't find a mention for that form the manual.
Does Swift has a defined initialization order of properties? If it does, what is the rule, and where can I find the rule?
This is due to the fact that you're using a Closure (a Function is just a special case of Closure that is unnamed) to initialize the _con1 property with a default value.
From the Apple provided iBook:
If you use a closure to initialize a property, remember that the rest
of the instance has not yet been initialized at the point that the
closure is executed. This means that you cannot access any other
property values from within your closure, even if those properties
have default values. You also cannot use the implicit self property,
or call any of the instance’s methods.
Even though the note above refers specifically to closures, it seems that trying to set the default value for a property to be that of another property directly also does not work.