Это скрипт на python для Xcode 3.2.4, который генерирует; свойства интерфейса, синтез реализации и сделки.
Чтобы установить, скопируйте этот скрипт, перейдите в меню скриптов XCode (от второго до последнего)
«Редактировать пользовательские сценарии ...»
Добавьте его в поле «Код», создайте новое имя сценария и вставьте приведенный ниже сценарий python.
Чтобы использовать, просто выберите переменные под @interface, а затем вызовите этот скрипт.
Затем он добавит все свойства @ в реализации
и все @synthesize и dealloc's.
Он не добавит IBOutlet ни к одной из ваших меток или кнопок, поскольку не знает этого, но это
легко добавить вручную.
Отступ сценария ниже является критическим, поэтому не меняйте его.
#!/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()