首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于生成/合成属性的Xcode脚本

用于生成/合成属性的Xcode脚本
EN

Stack Overflow用户
提问于 2009-07-20 01:27:13
回答 7查看 6.1K关注 0票数 9

有没有人有Xcode脚本来为类中的实例变量生成@property和@synthsize指令?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-01-01 08:22:06

我使用的是Accessorizer,它可以做很多事情。

http://www.kevincallahan.org/software/accessorizer.html

非常便宜,而且功能强大。

票数 7
EN

Stack Overflow用户

发布于 2009-07-20 01:30:01

这是我基于很久以前找到的一个,用Python重写的,改进了它可以一次生成多个属性,以及其他东西。

它将使用(copy)作为属性为所有选定的实例变量生成属性。

仍然有一些在一个文件中有多个@接口或@实现的边缘情况,以及一些具有不寻常的标识符或星号位置(如*const)的情况,但它应该涵盖大多数典型的编码风格。如果您修复了这些情况,请随时编辑/发布修改。

代码语言:javascript
复制
#!/usr/bin/python

# Takes a header file with one or more instance variables selected
# and creates properties and synthesize directives for the selected properties.

# Accepts google-style instance variables with a tailing underscore and
# creates an appropriately named property without underscore.

# Entire Document
# Home Directory
# Discard Output
# Display in Alert

import os
import re
import subprocess

# AppleScripts for altering contents of files via Xcode
setFileContentsScript = """\
on run argv
  set fileAlias to POSIX file (item 1 of argv)
  set newDocText to (item 2 of argv)
    tell application "Xcode"
      set doc to open fileAlias
      set text of doc to newDocText
    end tell
end run \
"""

getFileContentsScript = """\
on run argv
  set fileAlias to POSIX file (item 1 of argv)
    tell application "Xcode"
      set doc to open fileAlias
      set docText to text of doc
  end tell
  return docText
end run \
"""

# Get variables from Xcode
headerFileText = """%%%{PBXAllText}%%%"""
selectionStartIndex = %%%{PBXSelectionStart}%%%
selectionEndIndex = %%%{PBXSelectionEnd}%%%
selectedText = headerFileText[selectionStartIndex:selectionEndIndex]

headerFilePath = """%%%{PBXFilePath}%%%"""

# Look for an implementation file with .m or .mm extension
implementationFilePath = headerFilePath[:-1] + "m"
if not os.path.exists(implementationFilePath):
    implementationFilePath += "m"

instanceVariablesRegex = re.compile(
  """^\s*((?:(?:\w+)\s+)*(?:(?:\w+)))""" + # Identifier(s)
  """([*]?)\\s*""" + # An optional asterisk
  """(\\w+?)(_?);""", # The variable name
  re.M)

# Now for each instance variable in the selected section
properties = ""
synthesizes = ""

for lineMatch in instanceVariablesRegex.findall(selectedText):
    types = " ".join(lineMatch[0].split()) # Clean up consequtive whitespace
    asterisk = lineMatch[1]
    variableName = lineMatch[2]
    trailingUnderscore = lineMatch[3]

    pointerPropertyAttributes = "(copy) " # Attributes if variable is pointer
    if not asterisk:
      pointerPropertyAttributes = ""

    newProperty = "@property %s%s %s%s;\n" % (pointerPropertyAttributes,
                                             types,
                                             asterisk,
                                             variableName)

    # If there's a trailing underscore, we need to let the synthesize
    # know which backing variable it's using
    newSynthesize = "@synthesize %s%s;\n" % (variableName,
                                           trailingUnderscore and
                                           " = %s_" % variableName)

    properties += newProperty
    synthesizes += newSynthesize

# Check to make sure at least 1 properties was found to generate
if not properties:
  os.sys.stderr.writelines("No properties found to generate")
  exit(-1)

# We want to insert the new properties either immediately after the last
# existing property or at the end of the instance variable section
findLastPropertyRegex = re.compile("^@interface.*?{.*?}.*?\\n" +
                                   "(?:.*^\\s*@property.*?\\n)?", re.M | re.S)
headerInsertIndex = findLastPropertyRegex.search(headerFileText).end()

# Add new lines on either side if this is the only property in the file
addedNewLine = "\n"
if re.search("^\s*@property", headerFileText, re.M):
  # Not the only property, don't add
  addedNewLine = ""

newHeaderFileText = "%s%s%s%s" % (headerFileText[:headerInsertIndex],
                                addedNewLine,
                                properties,
                                headerFileText[headerInsertIndex:])

subprocess.call(["osascript",
                "-e",
                setFileContentsScript,
                headerFilePath,
                newHeaderFileText])


if not os.path.exists(implementationFilePath):
  os.sys.stdout.writelines("No implementation file found")
  exit(0)

implementationFileText = subprocess.Popen(
  ["osascript",
   "-e",
  getFileContentsScript,
   implementationFilePath],
  stdout=subprocess.PIPE).communicate()[0]

# We want to insert the synthesizes either immediately after the last existing
# @synthesize or after the @implementation directive
lastSynthesizeRegex = re.compile("^\\s*@implementation.*?\\n" +
                                "(?:.*^\\s*@synthesize.*?\\n)?", re.M | re.S)

implementationInsertIndex = \
  lastSynthesizeRegex.search(implementationFileText).end()

# Add new lines on either side if this is the only synthesize in the file
addedNewLine = "\n"
if re.search("^\s*@synthesize", implementationFileText, re.M):
  # Not the only synthesize, don't add
  addedNewLine = ""

newImplementationFileText = "%s%s%s%s" % \
                  (implementationFileText[:implementationInsertIndex],
                   addedNewLine,
                   synthesizes,
                   implementationFileText[implementationInsertIndex:])

subprocess.call(["osascript",
                 "-e",
                 setFileContentsScript,
                 implementationFilePath,
                 newImplementationFileText])

# Switch Xcode back to header file
subprocess.Popen(["osascript",
                  "-e",
                  getFileContentsScript,
                  headerFilePath],
                 stdout=subprocess.PIPE).communicate()
票数 2
EN

Stack Overflow用户

发布于 2010-09-18 04:32:54

这是一个用于Xcode 3.2.4的python脚本,用于生成;接口属性、实现合成和取消分配。要安装、复制此脚本,请转到Xcode脚本菜单(倒数第二个)“编辑用户脚本...”将其添加到Code下,创建一个新的脚本名称,然后将python脚本粘贴到下面。

要使用,只需选择@接口下的变量,然后调用此脚本。然后它会在实现中添加所有的@属性,以及所有的@synthesize和dealloc,它不会将IBOutlet添加到你的任何标签或按钮中,因为它不知道这一点,但这很容易手动添加。

下面脚本的缩进很关键,所以不要更改它。

代码语言:javascript
复制
#!/usr/bin/python


# Takes a header file with one or more instance variables selected
# and creates properties and synthesize directives for the selected properties.

# Accepts google-style instance variables with a tailing underscore and
# creates an appropriately named property without underscore.

# Xcode script options should be as follows:
# Entire Document
# Home Directory
# Discard Output
# Display in Alert

import os
import re
import subprocess

# AppleScripts for altering contents of files via Xcode
setFileContentsScript = """\
on run argv
set fileAlias to POSIX file (item 1 of argv)
set newDocText to (item 2 of argv)
tell application "Xcode"
set doc to open fileAlias
set text of doc to newDocText
end tell
end run \
"""

getFileContentsScript = """\
on run argv
set fileAlias to POSIX file (item 1 of argv)
tell application "Xcode"
set doc to open fileAlias
set docText to text of doc
end tell
return docText
end run \
"""

# Get variables from Xcode
headerFileText = """%%%{PBXAllText}%%%"""
selectionStartIndex = %%%{PBXSelectionStart}%%%
selectionEndIndex = %%%{PBXSelectionEnd}%%%
selectedText = headerFileText[selectionStartIndex:selectionEndIndex]

headerFilePath = """%%%{PBXFilePath}%%%"""

# Look for an implementation file with .m or .mm extension
implementationFilePath = headerFilePath[:-1] + "m"
if not os.path.exists(implementationFilePath):
implementationFilePath += "m"

instanceVariablesRegex = re.compile(
"""^\s*((?:(?:\\b\w+\\b)\s+)*(?:(?:\\b\\w+\\b)))\\s*""" + # Identifier(s)
"""([*]?)\\s*""" + # An optional asterisk
"""(\\b\\w+?)(_?\\b);""", # The variable name
re.M)

# Now for each instance variable in the selected section
properties = ""
synthesizes = ""
deallocs = ""

for lineMatch in instanceVariablesRegex.findall(selectedText):
    types = " ".join(lineMatch[0].split()) # Clean up consequtive whitespace

    asterisk = lineMatch[1]
    variableName = lineMatch[2]
    trailingUnderscore = lineMatch[3]

    pointerPropertyAttributes = "(nonatomic, retain) " # Attributes if variable is pointer
    if not asterisk:
        pointerPropertyAttributes = "(nonatomic, assign) "

    newProperty = "@property %s%s %s%s;\n" % (pointerPropertyAttributes,
                                       types,
                                       asterisk,
                                       variableName)

    # If there's a trailing underscore, we need to let the synthesize
    # know which backing variable it's using
    newSynthesize = "@synthesize %s%s;\n" % (variableName,
                                     trailingUnderscore and
                                     " = %s_" % variableName)
    # only do the objects
    if asterisk:
        newDealloc = "    [%s%s release];\n" % (variableName,
                    trailingUnderscore and
                                 " = %s_" % variableName)
    properties += newProperty
    synthesizes += newSynthesize
    # only add if it's an object
    if asterisk:
        deallocs += newDealloc


# Check to make sure at least 1 properties was found to generate
if not properties:
    os.sys.stderr.writelines("No properties found to generate")
    exit(-1)

# We want to insert the new properties either immediately after the last
# existing property or at the end of the instance variable section
findLastPropertyRegex = re.compile("^@interface.*?{.*?}.*?\\n" +
                         "(?:.*^\\s*@property.*?\\n)?", re.M | re.S)
headerInsertIndex = findLastPropertyRegex.search(headerFileText).end()

# Add new lines on either side if this is the only property in the file
addedNewLine = "\n"
if re.search("^\s*@property", headerFileText, re.M):
    # Not the only property, don't add
    addedNewLine = ""

newHeaderFileText = "%s%s%s%s" % (headerFileText[:headerInsertIndex],
                      addedNewLine,
                      properties,
                      headerFileText[headerInsertIndex:])

subprocess.call(["osascript",
      "-e",
      setFileContentsScript,
      headerFilePath,
      newHeaderFileText])


if not os.path.exists(implementationFilePath):
    os.sys.stdout.writelines("No implementation file found")
    exit(0)

implementationFileText = subprocess.Popen(
["osascript",
"-e",
getFileContentsScript,
implementationFilePath],
stdout=subprocess.PIPE).communicate()[0]

# We want to insert the synthesizes either immediately after the last existing
# @synthesize or after the @implementation directive
lastSynthesizeRegex = re.compile("^\\s*@implementation.*?\\n" +
                      "(?:.*^\\s*@synthesize.*?\\n)?", re.M | re.S)

implementationInsertIndex = \
lastSynthesizeRegex.search(implementationFileText).end()

# Add new lines on either side if this is the only synthsize in the file
addedNewLine = "\n"
if re.search("^\s*@synthesize", implementationFileText, re.M):
     # Not the only synthesize, don't add
    addedNewLine = ""

newImplementationFileText = "%s%s%s%s" % \
        (implementationFileText[:implementationInsertIndex],
         addedNewLine,
         synthesizes,
         implementationFileText[implementationInsertIndex:])

subprocess.call(["osascript",
       "-e",
       setFileContentsScript,
       implementationFilePath,
       newImplementationFileText])


implementationFileText = subprocess.Popen(
["osascript",
"-e",
getFileContentsScript,
implementationFilePath],
stdout=subprocess.PIPE).communicate()[0]

# We want to insert the deallocs either immediately after the last existing
# [* release] or after the [super dealloc]
lastDeallocRegex = re.compile("^\\s+\[super dealloc\];?\\n" +
                      "(?:.*^\\s+\[\w release\];?\\n)?", re.M | re.S)

deallocInsertIndex = \
lastDeallocRegex.search(implementationFileText).end() 

addedNewDeallocLine = "\n"
if re.search("^\s*\[\w release\];?", implementationFileText, re.M):
# Not the only dealloc, don't add
addedNewDeallocLine = ""


newImplementationFileText = "%s%s%s%s" % \
         (implementationFileText[:deallocInsertIndex],
          addedNewDeallocLine,
          deallocs,
          implementationFileText[deallocInsertIndex:])

subprocess.call(["osascript",
              "-e",
              setFileContentsScript,
              implementationFilePath,
              newImplementationFileText])      

# Switch Xcode back to header file
subprocess.Popen(["osascript",
        "-e",
        getFileContentsScript,
        headerFilePath],
       stdout=subprocess.PIPE).communicate()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1151393

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档