https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md
class MyObject { @objc var myString: String = "default"}// Works greatlet keypathstring = #keyPath(MyObject.myString)
Swift docs list the type作为“属性名称”传递给#keyPath().
The property name must be a reference to a property that is available in the Objective-C runtime. At compile time,the key-path Expression is replaced by a string literal.
可以独立保存这个“属性名称”,然后传递给#keyPath()来创建一个String吗?
let propertyname = MyObject.myString // error. How do I save?let string = #keyPath(propertyname)
是否支持要求属于特定类型的属性名称?
// something like thislet typedPropertyname: MyObject.Propertyname = myString // errorlet string = #keyPath(typedPropertyname)
最终目标将与需要NSExpression作为密钥路径的API进行交互.我想编写方便的方法,将有效的属性名称作为参数,而不是随机密钥路径字符串.理想情况下,由特定类型实现的属性名称.
func doSomethingForSpecificTypeProperty(_ propertyname: MyObject.Propertyname) { let keypathstring = #keyPath(propertyname) let Expression = NSExpression(forKeyPath: keypathstring) // ...}它看起来不可能.
这是解析密钥路径表达式的编译器代码:
/// expr-keypath:/// '#keyPath' '(' @R_301_1464@ ('.' @R_301_1464@) * ')'///ParserResult<Expr> Parser::parseExprKeyPath() { // Consume '#keyPath'. SourceLoc keywordLoc = consumetoken(tok::pound_keyPath); // Parse the leading '('. if (!Tok.is(tok::l_paren)) { diagnose(Tok,diag::expr_keypath_expected_lparen); return makeParserError(); } SourceLoc lParenLoc = consumetoken(tok::l_paren); // Handle code completion. SmallVector<IDentifIEr,4> names; SmallVector<SourceLoc,4> nameLocs; auto handleCodeCompletion = [&](bool hasDot) -> ParserResult<Expr> { ObjCKeyPathExpr *expr = nullptr; if (!names.empty()) { expr = ObjCKeyPathExpr::create(Context,keywordLoc,lParenLoc,names,nameLocs,Tok.getLoc()); } if (CodeCompletion) CodeCompletion->completeExprKeyPath(expr,hasDot); // Eat the code completion token because we handled it. consumetoken(tok::code_complete); return makeParserCodeCompletionResult(expr); }; // Parse the sequence of @R_301_1464@s. ParserStatus status; while (true) { // Handle code completion. if (Tok.is(tok::code_complete)) return handleCodeCompletion(!names.empty()); // Parse the next name. DeclnameLoc nameLoc; bool afterDot = !names.empty(); auto name = parseUnqualifIEdDeclname( afterDot,nameLoc,diag::expr_keypath_expected_property_or_type); if (!name) { status.setIsParseError(); break; } // Cannot use compound names here. if (name.isCompoundname()) { diagnose(nameLoc.getBasenameLoc(),diag::expr_keypath_compound_name,name) .fixItReplace(nameLoc.getSourceRange(),name.getBasename().str()); } // Record the name we parsed. names.push_back(name.getBasename()); nameLocs.push_back(nameLoc.getBasenameLoc()); // Handle code completion. if (Tok.is(tok::code_complete)) return handleCodeCompletion(false); // Parse the next period to continue the path. if (consumeIf(tok::period)) continue; break; } // Parse the closing ')'. SourceLoc rParenLoc; if (status.isError()) { skipUntilDeclStmtRBrace(tok::r_paren); if (Tok.is(tok::r_paren)) rParenLoc = consumetoken(); else rParenLoc = PrevIoUsLoc; } else { parseMatchingToken(tok::r_paren,rParenLoc,diag::expr_keypath_expected_rparen,lParenLoc); } // If we cannot build a useful Expression,just return an error // Expression. if (names.empty() || status.isError()) { return makeParserResult<Expr>( new (Context) ErrorExpr(SourceRange(keywordLoc,rParenLoc))); } // We're done: create the key-path Expression. return makeParserResult<Expr>( ObjCKeyPathExpr::create(Context,rParenLoc));}
此代码首先在括号内创建一个以句点分隔的名称列表,然后尝试将它们解析为表达式.它接受表达式而不是任何Swift类型的数据;它接受代码,而不是数据.
总结以上是内存溢出为你收集整理的swift – 传递给#keyPath()的非字符串“属性名称”可以独立保存吗?全部内容,希望文章能够帮你解决swift – 传递给#keyPath()的非字符串“属性名称”可以独立保存吗?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)