'PFObject' does not have a member named &#

2020-02-06 02:35发布

问题:

I understand, this particular error was already posted here and there and the code is somewhat basic, but I myself still unable to figure this one out & I need advice.

The thing is when I add the first two lines of code provided on parse.com for saving objects

var gameScore = PFObject(className:"GameScore")
gameScore["score"] = 1337

I get the following error for the second line:

'PFObject' does not have a member named 'subscript'

I'm on Xcode 6.3 beta 2. All required libraries are linked with binary, <Parse/Parse.h> imported via BridgeHeader.

What syntax should I use?

回答1:

This is happening due to the 1.6.4 version of the parse sdk which added Objective-C Nullability Annotations to the framework. In particular the file Parse/PFObject.h defines:

- (PF_NULLABLE_S id)objectForKeyedSubscript:(NSString *)key;

which is causing the Swift compile error. Removing the PF_NULLABLE_S fixes the problem.

On the other hand it seems correct that an object for a keyed subscript might be nil, so I suspect this is a Swift bug...



回答2:

The problem seems to be the changed method signature, as kashif suggested. Swift doesn't seem to be able to bridge to the Objective-C method because the signature no longer matches the subscript method names.

Workaround 1

You can work around this without modifying the framework by calling the subscript method directly, instead of using the [] operator:

Instead of using the instruction below for getting the value of a particular key:

let str = user["key-name"] as? Bool

Please use the following instruction:

let str = user.objectForKey("key-name") as? Bool

and

Instead of using the instruction below for setting the value of a particular key:

user["key-name"] = "Bla bla"

Please use the following instruction:

user.setObject("Bla bla", forKey: "key-name")

Workaround 2

Another solution is to add an extension on PFObject that implements the subscript member and calls setValue:forKey::

extension PFObject {
  subscript(index: String) -> AnyObject? {
    get {
      return self.valueForKey(index)
    }
    set(newValue) {
      if let newValue: AnyObject = newValue {
        self.setValue(newValue, forKey: index)
      }
    }
  }
}

Note that this second workaround isn't entirely safe, since I'm not sure how Parse actually implements the subscript methods (maybe they do more than just calling setValue:forKey - it has worked in my simple test cases, so it seems like a valid workaround until this is fixed in Parse/Swift.



回答3:

I've successfully run your exact code.

First, make sure you are indeed saving the object in the background, after you set the new value:

gameScore.save()

I would double check for misspellings in the class name and subclass; if they are incorrect, it will not work.

If that's not the problem, verify in Parse that the "score" subclass is set to be a number. If you accidentally set it to be a string, setting it as an integer will not work.

If these suggestions have not hit the solution, then I'm not sure what the problem is. Hope I helped.



回答4:

I encountered a similar error with Parse 1.6.4 and 1.6.5 in the PFConstants.h header file with method parameters.

Xcode 6.3 beta 4 has a note in the "New in..." section regarding nullability operators.

Moving the nullability operator between the pointer operator and the variable name seems to comply/compile.

Changing:

PF_NULLABLE_S NSError *error

to:

NSError * PF_NULLABLE_S error 

  (i.e., NSError* __nullable error)

... resolved the compiler error.

This also worked for block parameters defined with id. So...

PF_NULLABLE_S id object

becomes:

id PF_NULLABLE_S object

In the above case, perhaps:

- (id PF_NULLABLE_S)objectForKeyedSubscript:(NSString *)key;

I.e., the nullability operator is after the pointer type.



回答5:

I know its been a while but I encountered a similar problem when I was starting my first Parse application with SDK version 1.9.1.

The Quickstart guide had the code below as an example as to how to save values:

    let testObject = PFObject(className: "TestObject")
testObject["foo"] = "bar"
testObject.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
  println("Object has been saved.")
}

But, the line testObject["foo"] = "bar" returned the error 'PFObject' does not have a member named 'subscript'. I was able to work around the problem by changing the line to testObject.setValue("bar", forKey: "foo"). (As suggested by a tutorial video on YouTube: https://www.youtube.com/watch?v=Q6kTw_cK3zY)