I have got an unusual problem in swift 2.3 to Swift 3.0. Once I convert the code from 2.3 to 3.0, i am getting this issue:'Ambiguous reference to member 'Subscript',
Code are :
dynamic func onDataNotification(notification: NSNotification) {
var data = notification.userInfo as! Dictionary<NSString, ARoutedMessage>
if let packet = data[AEnginePacketDataKey] as? AEngineMessage,
currentDevice = self.currentDevice() {
if packet.messageId == MessageId.message && currentDevice.isDevice() {
// Some code
}
}
}
Getting error on let packet = data[AEnginePacketDataKey] as Ambiguous reference to member 'Subscript', I don't understand why?. Other:
// String
extern NSString *AEnginePacketDataKey;
//ARoutedMessage Class
#interface ARoutedMessage : NSObject
#property NSMutableArray *payloadParameters;
#end
//AEngineMessage Class
#interface AEngineMessage : ARoutedMessage
#property (readonly)MessageId messageId;
- (id) initWithMessageId:(MessageId) mId;
#end
Please help me out.
The "ambiguous reference" error is telling you that the variable you're trying to use as a subscript is the wrong type.
In this case data is a dictionary that is expecting an NSString subscript. It looks like AEnginePacketDataKey is defined as a pointer to an NSString in your Objective C code, but you don't show where (if) anything is assigned to it. Make sure you assign an actual NSString to it before you try to use it as a subscript of data.
Related
I am working on an old Swift 3 project and I'm getting this error after updating it to Swift 4.2. It seems to work fine in Swift 3. I had to declare let NSURLPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String) because NSURLPboardType does not exist in Swift 4.2 but otherwise the code is the same.
enum SparkleDrag {
static let type = "com.razeware.StickerDrag.AppAction"
static let action = "make sparkles"
}
let NSURLPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String)
var nonURLTYpes: Set<String> {return [String(kUTTypeTIFF), SparkleDrag.type]}
var acceptableTypes: Set<String> {return [nonURLTYpes.union(NSURLPboardType)]}
The "u" in union is underlined with the error but I don't quite understand the nature of the problem. Any guidance would be much appreciated.
The problem is that NSURLPboardType is not a Set<String>, so the union cannot work.
If you're trying to get something like this:
["com.razeware.StickerDrag.AppAction", "public.url", "public.tiff"]
in aceptableTypes, you can simply forgo NSURLPboardType and do this:
enum SparkleDrag {
static let type = "com.razeware.StickerDrag.AppAction"
static let action = "make sparkles"
}
// let NSURLPboardType = NSPasteboard.PasteboardType(kUTTypeURL as String)
var nonURLTYpes: Set<String> {return [String(kUTTypeTIFF), SparkleDrag.type]}
var acceptableTypes: Set<String> {return nonURLTYpes.union([kUTTypeURL as String])}
I recently updated my Xcode to Xcode 8.3.2 and ran the swift syntax updater. As a result of this update my Parse classes no longer work and I am not sure how fix them.
The error I am receiving is 'Static member 'registerSubclass' cannot be used on instance of type 'County'
The class looks like this.
import Foundation
class County : PFObject, PFSubclassing {
private lazy var __once: () = {
self.registerSubclass()
}()
#NSManaged var Name: String
override class func initialize() {
var onceToken : Int = 0;
_ = self.__once
}
class func parseClassName() -> String{
return "County"
}
}
I am also not understanding why in this update I am getting errors on when using self to call class level methods from within an enclosure?
Why the following Swift3 code results in error value of type (NSObject) -> () -> MyView has no member getSomeButton in Xcode 8?
lazy var someButton = {
return self.getSomeButton // ERROR
}()
private func getSomeButton() -> UIButton {
return UIButton()
}
Actually, the error message is totally misleading and should be something like can't infer closure return type. Specifying variable type solves the problem. Hope this help someone.
lazy var someButton: UIButton = {
return self.getSomeButton // OK
}()
I want to change the properties of some objects (Labels, Buttons..), I created using the Storyboard out of c++-code. So I need a way of running ViewController-class-internal methods.
Is there any proper way to do this? Is there another possibility?
I've tried using callbacks, but there is always this barrier between global and internal in the ViewController-class. Thanks in advance!
EDIT:
Since I don't know how to access a swift class out of c++ code, i cannot give any proper examples, but I thought of something like this (pseudo code):
In c++:
int main(){
say_hello();
}
and in Swift:
class ViewController: NSViewController {
#IBOutlet weak var label: NSTextField!
func say_hello(){
label.stringValue = "Hello"
}
}
Here is an oversimplified example of how this could be done using an Objective-C++ wrapper, as suggested by Richard. Memory management and thread safety aspects, and many other things, are not addressed here. In this example there is a 1-to-1 relationship between Swift and C++ class instances. Also, Swift object pointers are used as identifiers to decide which Swift object should receive a notification. This is kind of dangerous, see comments in the code below. Using more sophisticated data structures in the Objective-C++ wrapper to maintain a connection between Swift and C++ objects, one could easily work around this danger and support relationships other than 1-to-1.
First of all, here is a C++ class that triggers changes in Swift code:
typedef void (*cb_t)(const char *, void *);
class MyClassCPP {
public:
MyClassCPP(cb_t callBack, void * p) : myCallBack(callBack), clientPtr(p) {}
void doWork(); // perform some work and invoke the callback
private:
cb_t myCallBack;
void * clientPtr;
};
void MyClassCPP::doWork() {
myCallBack("C++ code at work...", clientPtr);
}
Here is an Objective-C++ wrapper interface that should be made visible to Swift code via the bridging header, directly or indirectly. Please note that it does not reference any C++ types.
#class SwiftClass; // forward declaration
// can't include *-Swift.h in a header
#interface OCWrapper : NSObject
-(instancetype)init:(SwiftClass * )sc;
-(void)requestWorkFromCPP;
#end
And here is the wrapper implementation. It does reference C++ types. We cannot provide a Swift global function as a callback to C++ code, but we can provide an Objective-C++ global function for this purpose.
// Extension that deals with C++ specifics that can't be visible to Swift
#interface OCWrapper ()
{
MyClassCPP * myClassCPP;
}
#end
void callBack(const char * msg, void * swiftClient)
{
// Danger: what if swiftClient does not point to a SwiftClass instance?
[(__bridge SwiftClass*)swiftClient sayHello:
[[NSString alloc] initWithBytes: msg length:strlen(msg)
encoding:NSASCIIStringEncoding]];
}
#implementation OCWrapper
-(instancetype)init:(SwiftClass * )sc
{
myClassCPP = new MyClassCPP(callBack, (__bridge void*)sc);
return self;
}
-(void)requestWorkFromCPP{
myClassCPP->doWork();
}
#end
The above should be in an Objective-C++ file. Create an Objective-C file and then rename it to have the .mm extension. You will also need to include the *-Swift.h header, so Objective-C++ can use Swift types.
Finally, here is some Swift code that uses the C++ code via the Objective-C++ wrapper:
// This is like your Swift view controller
class SwiftClass : NSObject
{
var label = "[Empty]"
var name : String;
init(name : String) {
self.name = name
}
func sayHello(greeting : String) {
label = "SwiftClass named " + name + " received greeting: " + greeting
}
}
...
let sc = SwiftClass( name : "Zero")
let ocWrapper = OCWrapper(sc)
let sc1 = SwiftClass( name : "One" )
let ocWrapper1 = OCWrapper(sc1)
ocWrapper1.requestWorkFromCPP()
print("The label value from C++: \(sc1.label)")
ocWrapper.requestWorkFromCPP()
print("The label value from C++: \(sc.label)")
...
I have spent a few hours on this one, as I thought first that it was again an issue while migrating to swift2 with AnyObject versus PFObject. But apparently not! Here is the code:
class TimelineViewController: UIViewController, TimelineComponentTarget {
var timelineComponent: TimelineComponent<Post, TimelineViewController>!
override func viewDidLoad() {
super.viewDidLoad()
timelineComponent = TimelineComponent(target: self)
self.tabBarController?.delegate = self
}
Xcode returns on the 'self' of the last line:
Cannot assign value of type 'TimelineViewController' to type 'UITabBarControllerDelegate?'
Any help would be really appreciated, I would love to finally compile my code :)
Thanks!
I understood from the error message that I was trying to assign self as the delegate of a UITabBarControllerDelegate.
Or the TimeLineViewController is not a UITabBarControllerDelegate. I have therefore adopt this protocol.
class TimelineViewController: UIViewController, TimelineComponentTarget, UITabBarControllerDelegate {
It now works properly. Thanks!