It's not a duplicate cause with lazy i have an issu too :
"A C function pointer cannot be formed from a closure that captures context"
In my main class I have "detectChangeMidi" but in this code, when I try to call a function I don't understand why I can't.
(i can't use var too, anything of my class)
I'm not expert in swift, then try to explain to me what's going one.
I use the CoreMidi librarie.
UPDATE :
I replace the code by minimaliste code for better entendement.
import Foundation
import CoreMIDI
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
gestionMidi()
//...
}
func gestionMidi() {
//...
let midiNotif:MIDINotifyProc = detectChangeMidi
MIDIClientCreate("Swift3 Test Client" as CFString, midiNotif, nil, &midiClient)
//...
}
func plop(){
print("bla bla bla")
}
let detectChangeMidi: #convention(c) (UnsafePointer<MIDINotification>, UnsafeMutableRawPointer?) -> Swift.Void =
{ midiNotification,unkown in
var notification = midiNotification.pointee
self.plop() //problem here
//...
}
}
Your entire agenda here is misguided; it is not at all obvious what you can be trying to do. You cannot declare a property or function as being convention(c) and also refer to self. But you don't need to! If your goal is to pass a function as a parameter where a C pointer-to-function is expected, just pass the function. Anyway you'll have a much easier time in Swift if you call MIDIClientCreateWithBlock(_:_:_:) instead.
The problem is with the scope as I can judge from the error message.
Also the thing to get attention to is that you're executing plop() in closure, and that requires self.plop().
also midiNotification,unkown in - unkown seems to be a typo.
Check where you declare the function itself. From this snippet it's hard to understand what's your declaration scope.
Related
I'm pretty new to this, but I've been managing to stumble my way through to getting the current location of my IOS device...etc The only problem is, I can't seem to get the GMSPlace to stay assigned to the property I declared at the top of my class, which I plan on using in another function.
It works fine when I run a print statement from within the scope of the callback, but when I seem to use the value stored in 'queryPlace', it returns a 'nil'. I'm guessing its a scope and lifetime issue, but I'm not sure if I understand it properly.
Here is the code that I'm having difficulty with understanding why it won't hold the value of 'place':
import UIKit
import CoreLocation
import GoogleMaps
import GooglePlaces
class GoogleMapSearchVC : UIViewController, CLLocationManagerDelegate {
var placeQuery: GMSPlace?
func loadCurrentPosition() {
print("Loading Positions and Coords")
// Invoke Callback method to get GMSPlacesLiklihood
placesClient.currentPlace(callback: { (placeLikelihoodList, error) -> Void in
if let error = error {
print("Pick Place error: \(error.localizedDescription)")
return
}
if let placeLikelihoodList = placeLikelihoodList {
let place = placeLikelihoodList.likelihoods.first?.place
if let place = place {
self.updateMap(newLocation: place)
// updateMap function moves camera to current location.
self.placeQuery = place
// If I print(self.placeQuery) here, it works fine, but later on placeQuery returns nil.
}
}
})
}
func doSomethingWithPlace() {
print(self.placeQuery?coordinate.latitude)
// Returns 'nil'
}
}
Thank you in advance for any help, very much appreciated.
No, there shouldn't be any "lifetime" issues. placeQuery is bound to the lifetime of your view controller instance.
Just a stupid guess (sorry if that was obvious): Are you sure that doSomethingWithPlace() accesses the variable after the callback has returned? Since you're setting it only in the asynchronous callback, the variable will not be set when loadCurrentPosition() returns.
If that's not the issue, here's a debugging tip to find out where this value is set back to nil: You can set a breakpoint at the line of the variable declaration and the debugger will break in the setter. If you're more into "print debugging", you can also add a didSet clause:
var placeQuery: GMSPlace? {
didSet {
print("setting placeQuery from \(oldValue) to \(placeQuery)")
}
}
This one has me stumped. I can't figure out why Swift is complaining that self.init is called more than once in this code:
public init(body: String) {
let parser = Gravl.Parser()
if let node = parser.parse(body) {
super.init(document: self, gravlNode: node)
} else {
// Swift complains with the mentioned error on this line (it doesn't matter what "whatever" is):
super.init(document: self, gravlNode: whatever)
}
}
Unless I'm missing something, it's very obvious that it is only calling init once. Funnily enough if I comment out the second line Swift complains that Super.init isn't called on all paths, lol.
What am I missing?
Update:
Ok so the problem was definitely trying to pass self in the call to super.init. I totally forgot I was doing that, ha. I think I had written that experimentally and gotten it to compile and thought that it might actually work, but looks like it's actually a bug that it compiled that way at all.
Anyhow, since passing self to an initializer is kind of redundant since it's the same object, I changed the parent initializer to accept an optional document parameter (it's just an internal initializer so no big deal) and if it's nil I just set it to self in the parent initializer.
For those curious, this is what the parent initializer (now) looks like:
internal init(document: Document?, gravlNode: Gravl.Node) {
self.value = gravlNode.value
super.init()
self.document = document ?? self as! Document
// other stuff...
}
I suspect this is a bad diagnostic (i.e the wrong error message). It would be very helpful if you had a full example we could experiment with, but this line doesn't make sense (and I suspect is the underlying problem):
super.init(document: self, gravlNode: node)
You can't pass self to super.init. You're not initialized yet (you're not initialized until you've called super.init). For example, consider the following simplified code:
class S {
init(document: AnyObject) {}
}
class C: S {
public init() {
super.init(document: self)
}
}
This leads to error: 'self' used before super.init call which I believe is the correct error.
EDIT: I believe Hamish has definitely uncovered a compiler bug. You can exploit it this way in Xcode 8.3.1 (haven't tested on 8.3.2 yet):
class S {
var x: Int
init(document: S) {
self.x = document.x
}
}
class C: S {
public init() {
super.init(document: self)
}
}
let c = C() // malloc: *** error for object 0x600000031244: Invalid pointer dequeued from free list
Newbie question. I am simply trying to declare a class (or even struct) as a separate Swift file and then build it or use it inside a separate class. Consider this:
import Foundation
class PayloadTest{
var label: String
init(label:String) {
self.label = label
}
}
---- then separate file
import WatchKit
import Foundation
class InterfaceController2: WKInterfaceController {
var payloadtest = PayloadTest(label: "test string init")
payloadtest.label = "test" // this line gives error - says it was expecting a declaration
.
.
.
}
I can't figure out why if I make a class or struct at the same level in my watchOS extension, it is not allowed to be accessed or recognized when I try to access the variables.
As dfd mentioned in the comment section this is a scope issue. In many programming languages you just can't write statements (expressions) which is not either a declaration or initialization or a method call outside the function or a method.
Let me explain what I said,
In a class or a structure definition any statements(expressions) apart from declaration & initialization should be present in the function (method) definition.
class PayloadTest{
//The below statement is declaration, which declares label is an property of type string.
var label: String
init(label:String) {
//The below statement is an assignment, and it compiles and execute fine as this is inside a init method.
self.label = label
}
}
However in your second snippet,
import WatchKit
import Foundation
class InterfaceController2: WKInterfaceController {
//The below statement compiles fine even tough it isn't present inside a method coz it is initialization statement.
var payloadtest = PayloadTest(label: "test string init")
//However the compiler complains about the below assignment statement because, this is neither an declaration nor an initialization statement and it should not be outside method.
//So you've to keep this statement inside a method for compiler to stop complaining.
payloadtest.label = "test" // this line gives error - says it was expecting a declaration
....
}
To make the second snippet work put the below line of code in a method and call that method,
payloadtest.label = "test"
So always remember any statements apart from declaration, initialization should be present inside a method or function definition and this applies to most of the languages.
Please go through the various scope levels present. HTH :)
You can't have an expression nested in a class like that. You can get around this by putting your code in a closure which you immediately call:
class InterfaceController2: WKInterfaceController {
var payloadtest = {
let pt = PayloadTest(label: "test string init")
pt.label = "test"
return pt
}()
you can try to move that code in a function. (Swift 3.0 version)
class InterfaceController: WKInterfaceController {
var payloadtest = PayloadTest(label: "test string init")
fileprivate func test() {
payloadtest.label = "test" // tape this line in a function
}
}
Try this below code work with optional type -
class PayloadTest {
var label: String?
init(label:String) {
self.label = label
}
}
protocol IDataSource:AnyObject{
typealias DS;
typealias U;
func dataSource(ds:DS, index:Int?);
func dataSource(ds:DS, data:[U]);
}
class DataSource<T:AnyObject>{
var map = [NSManagedObjectID:T]();
var data = [T]();
var ctrls:NSHashTable = NSHashTable.weakObjectsHashTable();
func find(value:T)->Int?;
var selected:T?;
func setNeedsUpdate<Bar:IDataSource where Bar.U==T,Bar.DS==DSGen>(){
for ctrl in self.ctrls.allObjects {
let client = ctrl as! Bar;
client.dataSource(self, data:self.data);
}
}
func foo(){
// error
setNeedsUpdate()
}
}
How I can call method setNeedsUpdate()?
compiler error " Cannot invoke 'setNeedsUpdate' with no arguments"
have found some decision, but decision demand extra parameter
func setNeedsUpdate<Bar:IDataSource where Bar.U==T,Bar.DS==DSGen>(type:Bar.Type){
for ctrl in self.ctrls.allObjects {
let client = ctrl as! Bar;
client.dataSource(self, data:self.data);
}
}
func foo<Bar:IDataSource where Bar.U==T,Bar.DS==DSGen>(){
// error
setNeedsUpdate(Bar.self)
}
func setNeedsUpdate<Bar:IDataSource where Bar.U==T,Bar.DS==DSGen>(){
You can declare a generic function like this, but in isolation you can never call it, because you have provided no way to specify the generic placeholder. In other words, there is nothing here that would tell the compiler what type Bar actually is. Thus, as it stands, this is a useless function.
I think the first thing to ask yourself might be why this needs to be a generic at all - and why, indeed, the class DataSource needs to be a generic. If you know that ctrls will be hash table consisting of IDataSources, it's hard to see what the generic is for. It's not clear what you're trying to accomplish but it seems that you might be overthinking it.
I'm trying to create a protocol in Swift I can use for object construction. The problem I'm running into is that I need to store the type information so the type can be constructed later and returned in a callback. I can't seem to find a way to store it without either crashing the compiler or creating build errors. Here's the basics (a contrived, but working example):
protocol Model {
init(values: [String])
func printValues()
}
struct Request<T:Model> {
let returnType:T.Type
let callback:T -> ()
}
We have a simple protocol that declares a init (for construction) and another func printValues() (for testing). We also define a struct we can use to store the type information and a callback to return the new type when its constructed.
Next we create a constructor:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
A couple things to note: This causes a compiler crash. It can't figure this out for some reason. The problem appears to be var callbacks: [Request<Model>] = []. If I comment out everything else, the compiler still crashes. Commenting out the var callbacks and the compiler stops crashing.
Also, the func construct works fine. But it doesn't store the type information so it's not so useful to me. I put in there for demonstration.
I found I could prevent the compiler from crashing if I remove the protocol requirement from the Request struct: struct Request<T>. In this case everything works and compiles but I still need to comment out let model = request.returnType(values: ["value1", "value2"]) in func next(). That is also causing a compiler crash.
Here's a usage example:
func construct() {
let constructor = Constructor()
let request = Request(returnType: TypeA.self) { req in req.printValues() }
//This works fine
constructor.construct(TypeA.self) { a in
a.printValues()
}
//This is what I want
constructor.queueRequest(request)
constructor.next() //The callback in the request object should be called and the values should print
}
Does anyone know how I can store type information restricted to a specific protocol to the type can later be constructed dynamically and returned in a callback?
If you want the exact same behavior of next I would suggest to do this:
class Constructor {
// store closures
var callbacks: [[String] -> ()] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest<T:Model>(request: Request<T>) {
// some code from the next function so you don't need to store the generic type itself
// **EDIT** changed closure to type [String] -> () in order to call it with different values
callbacks.append({ values in
let model = request.returnType(values: values)
request.callback(model)
})
}
func next(values: [String]) {
callbacks.first?(values)
}
}
Now you can call next with your values. Hopefully this works for you.
EDIT: Made some changes to the closure type and the next function
Unfortunately there is no way to save specific generic types in an array and dynamically call their methods because Swift is a static typed language (and Array has to have unambiguous types).
But hopefully we can express something like this in the future like so:
var callbacks: [Request<T: Model>] = []
Where T could be anything but has to conform to Model for example.
Your queueRequest method shouldn't have to know the generic type the Request it's being passed. Since callbacks is an array of Request<Model> types, the method just needs to know that the request being queued is of the type Request<Model>. It doesn't matter what the generic type is.
This code builds for me in a Playground:
class Constructor {
var callbacks: [Request<Model>] = []
func construct<T:Model>(type:T.Type, callback: T -> ()) {
callback(type(values: ["value1", "value2"]))
}
func queueRequest(request: Request<Model>) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
let model = request.returnType(values: ["value1", "value2"])
request.callback(model)
}
}
}
So I found an answer that seems to do exactly what I want. I haven't confirmed this works yet in live code, but it does compile without any errors. Turns out, I needed to add one more level of redirection:
I create another protocol explicitly for object construction:
protocol ModelConstructor {
func constructWith(values:[String])
}
In my Request struct, I conform to this protocol:
struct Request<T:Model> : ModelConstructor {
let returnType:T.Type
let callback:T -> ()
func constructWith(values:[String]) {
let model = returnType(values: values)
callback(model)
}
}
Notice the actual construction is moved into the Request struct. Technically, the Constructor is no longer constructing, but for now I leave its name alone. I can now store the Request struct as ModelConstructor and correctly queue Requests:
class Constructor {
var callbacks: [ModelConstructor] = []
func queueRequest(request: Request<Model>) {
queueRequest(request)
}
func queueRequest(request: ModelConstructor) {
callbacks.append(request)
}
func next() {
if let request = callbacks.first {
request.constructWith(["value1", "value2"])
callbacks.removeAtIndex(0)
}
}
}
Note something special here: I can now successfully "queue" (or store in an array) Request<Model>, but I must do so indirectly by calling queueRequest(request: ModelConstructor). In this case, I'm overloading but that's not necessary. What matters here is that if I try to call callbacks.append(request) in the queueRequest(request: Request<Model>) function, the Swift compiler crashes. Apparently we need to hold the compiler's hand here a little so it can understand what exactly we want.
What I've found is that you cannot separate Type information from Type Construction. It needs to be all in the same place (in this case it's the Request struct). But so long as you keep construction coupled with the Type information, you're free to delay/store the construction until you have the information you need to actually construct the object.