ฉันจะแสดงการแก้ไขเวอร์ชันแอปพลิเคชันในชุดการตั้งค่าแอปพลิเคชันของฉันได้อย่างไร


91

ฉันต้องการรวมเวอร์ชันแอปพลิเคชันและการแก้ไขภายในเช่น 1.0.1 (r1243) ไว้ในชุดการตั้งค่าแอปพลิเคชันของฉัน

ไฟล์ Root.plist มีแฟรกเมนต์เช่นนี้ ...

     <dict>
        <key>Type</key>
        <string>PSTitleValueSpecifier</string>
        <key>Title</key>
        <string>Version</string>
        <key>Key</key>
        <string>version_preference</string>
        <key>DefaultValue</key>
        <string>VersionValue</string>
        <key>Values</key>
        <array>
            <string>VersionValue</string>
        </array>
        <key>Titles</key>
        <array>
            <string>VersionValue</string>
        </array>
    </dict>

และฉันต้องการแทนที่สตริง "VersionValue" ในเวลาสร้าง

ฉันมีสคริปต์ที่สามารถแยกหมายเลขเวอร์ชันจากที่เก็บของฉันสิ่งที่ฉันต้องการคือวิธีการประมวลผล (ขั้นตอนก่อน) ไฟล์ Root.plist ในเวลาสร้างและแทนที่หมายเลขการแก้ไขโดยไม่ส่งผลกระทบต่อไฟล์ต้นฉบับ

คำตอบ:


69

มีวิธีแก้ปัญหาอื่นที่ง่ายกว่าคำตอบก่อนหน้านี้มาก Apple รวมเครื่องมือบรรทัดคำสั่งที่เรียกว่าPlistBuddyไว้ในตัวติดตั้งส่วนใหญ่และรวมไว้ใน Leopard ที่/usr/libexec/PlistBuddy.

เนื่องจากคุณต้องการแทนที่VersionValueโดยสมมติว่าคุณมีค่าเวอร์ชัน$newVersionคุณสามารถใช้คำสั่งนี้:

/usr/libexec/PlistBuddy -c "Set :VersionValue $newVersion" /path/to/Root.plist

ไม่จำเป็นต้องเล่นซอด้วยสำนวน sed หรือปกติวิธีนี้ค่อนข้างตรงไปตรงมา ดูหน้าคนสำหรับคำแนะนำโดยละเอียด คุณสามารถใช้ PlistBuddy เพื่อเพิ่มลบหรือแก้ไขรายการใด ๆ ในรายการคุณสมบัติ ตัวอย่างเช่นเพื่อนของฉันบล็อกเกี่ยวกับการเพิ่มหมายเลขบิลด์ใน Xcodeโดยใช้ PlistBuddy

หมายเหตุ:หากคุณระบุเฉพาะเส้นทางไปยัง plist PlistBuddy จะเข้าสู่โหมดโต้ตอบดังนั้นคุณสามารถออกคำสั่งหลายคำสั่งก่อนที่จะตัดสินใจบันทึกการเปลี่ยนแปลง ฉันขอแนะนำให้ทำสิ่งนี้ก่อนที่จะวางลงในสคริปต์สร้างของคุณ


20
ดูเหมือนว่าฉันจะหาวิธีที่ถูกต้องในการอ้างถึงหมายเลขเวอร์ชันใน plist ของฉัน ในกรณีของฉันมันกลายเป็น / usr / libexec / PlistBuddy Settings.bundle / Root.plist -c "set PreferenceSpecifiers: 0: DefaultValue $ newversion" - หวังว่าจะเป็นประโยชน์กับคนอื่น ๆ
JosephH

Quinn Taylor, JosephH ขอบคุณสำหรับคำตอบของคุณฉันสามารถใช้หมายเลขเวอร์ชันแอพของฉันโดยอัตโนมัติใน Settings.bundle +1 สำหรับคุณทั้งคู่ ;-)
Niko

7
จากเฟสการสร้าง "Run Script" ที่กำหนดเองฉันต้องรวมพา ธ เพิ่มเติมไปยัง Root.plist: / usr / libexec / PlistBuddy $ {TARGET_BUILD_DIR} / $ {FULL_PRODUCT_NAME} /Settings.bundle/Root.plist -c "set PreferenceSpecifiers: 0: DefaultValue $ newVersion "
Chris Vasselli

2
เพื่อความสมบูรณ์นี่เป็นอีกแนวทางหนึ่งของ PListBuddy ที่ใช้ได้ผลสำหรับฉัน: xcodehelp.blogspot.com/2012/05/…
koen

วิธีที่ถูกต้องที่สุดคือ/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:0:DefaultValue ${newVersion}" "${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Settings.bundle/Root.plist"
kambala

66

วิธีแก้ปัญหาสำหรับคนขี้เกียจของฉันคืออัปเดตหมายเลขเวอร์ชันจากรหัสแอปพลิเคชันของฉัน คุณสามารถมีค่าเริ่มต้น (หรือว่าง) ใน Root.plist จากนั้นที่ใดที่หนึ่งในรหัสเริ่มต้นของคุณ:

NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
[[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"];

สิ่งเดียวที่จับได้คือแอปของคุณจะต้องถูกเรียกใช้อย่างน้อยหนึ่งครั้งเพื่อให้เวอร์ชันที่อัปเดตปรากฏในแผงการตั้งค่า

คุณสามารถนำแนวคิดนี้ไปปรับปรุงและอัปเดตเช่นการนับจำนวนครั้งที่แอปของคุณเปิดตัวหรือข้อมูลที่น่าสนใจอื่น ๆ


9
วิธีนี้จะได้ผลยกเว้นหากผู้ใช้เข้าไปที่การตั้งค่าก่อนที่จะเปิดแอปของคุณ
Moshe

9
@Moshe True แต่เพื่อจัดการกับสิ่งนี้อย่างหรูหราคุณสามารถระบุค่าเริ่มต้นภายในไฟล์. plist บางทีอาจจะเป็น 'ยังไม่เปิดตัว'
Carlos P

1
แม้ว่านักพัฒนาส่วนใหญ่อาจตั้งค่าCFBundleShortVersionStringและCFBundleVersionเป็นค่าเดียวกัน แต่CFBundleShortVersionStringก็เป็นสิ่งที่Apple ต้องการให้คุณพิจารณาเวอร์ชันที่วางจำหน่ายซึ่งจะเป็นสิ่งที่คุณแสดงให้ผู้ใช้เห็น CFBundleVersionอาจเป็นหมายเลขเวอร์ชันภายในซึ่งคุณอาจไม่ควรแสดงให้ผู้ใช้เห็น (หากแตกต่างกัน)
Nate

3
ฉันพลาดอะไรไปรึเปล่า? นี่คือสิ่งที่ฉันกำลังทำอยู่ แต่ค่าไม่ได้รับการเปลี่ยนแปลง พวกคุณไม่ได้ใช้พร็อพเพอร์ตี้ Title ซึ่งฉันเชื่อว่าอ่านอย่างเดียวหรือเปล่า?
samson

2
นอกจากนี้ยังมีปัญหาอีกอย่างหนึ่งเมื่ออัปเดตแอปพลิเคชัน ชุดการตั้งค่าจะยังคงแสดงเวอร์ชันบิวด์เก่าจนกว่าแอปพลิเคชันที่อัปเดตจะเปิดใช้งานอย่างน้อยหนึ่งครั้ง
Legoless

62

จากคำตอบของ @ Quinn นี่คือกระบวนการและรหัสการทำงานทั้งหมดที่ฉันใช้เพื่อทำสิ่งนี้

  • เพิ่มชุดการตั้งค่าลงในแอปของคุณ อย่าเปลี่ยนชื่อ
  • เปิด Settings.bundle / Root.plist ในโปรแกรมแก้ไขข้อความ

แทนที่เนื้อหาด้วย:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"     "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Title</key>
            <string>About</string>
            <key>Type</key>
            <string>PSGroupSpecifier</string>
        </dict>
        <dict>
            <key>DefaultValue</key>
            <string>DummyVersion</string>
            <key>Key</key>
            <string>version_preference</string>
            <key>Title</key>
            <string>Version</string>
            <key>Type</key>
            <string>PSTitleValueSpecifier</string>
        </dict>
    </array>
    <key>StringsTable</key>
    <string>Root</string>
</dict>
</plist>
  • สร้างเฟสการสร้างRun Scriptย้ายไปอยู่หลังเฟสคัดลอก Bundle Resources เพิ่มรหัสนี้:

    cd "${BUILT_PRODUCTS_DIR}"
    buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}" )
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $buildVersion" "${WRAPPER_NAME}/Settings.bundle/Root.plist"
    
  • แทนที่ MyAppName ด้วยชื่อแอปจริงของคุณและ 1 หลัง PreferenceSpecifiers เป็นดัชนีของรายการเวอร์ชันของคุณในการตั้งค่า ตัวอย่าง Root.plist ข้างต้นมีไว้ที่ดัชนี 1


ฉันคิดว่านี่เป็นวิธีที่ดีที่สุด
Tony

ฉันลองสิ่งนี้และฉันเห็นค่า Title เปลี่ยนไปในชุดการตั้งค่าของฉัน ชื่อปรากฏใน InAppSettingsKit แต่ค่าจะไม่เปลี่ยนแปลงจากเวอร์ชันเริ่มต้น ชื่อไม่เคยปรากฏในแอปการตั้งค่า ฉันยอมแพ้และฉันจะเปิดกล่องโต้ตอบเมื่อผู้ใช้เลือก 'เกี่ยวกับ' ในเมนู '
bugloaf

เมื่อใช้วิธีนี้การตั้งค่าจะไม่อ่านอย่างเดียว เช่นฉันสามารถแตะที่การตั้งค่าหมายเลขเวอร์ชันใน settings.app และสามารถแก้ไขได้
motionpotion

8
สคริปต์ทุบตี @ Ben-Clayton ใส่ไม่ได้ผลสำหรับฉันดังนั้นฉันจึงสร้างใหม่ตามคำตอบของเขานี่คือ:buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}") /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:3:DefaultValue $buildVersion" "${SRCROOT}/Settings.bundle/Root.plist"
Luis Ascorbe

1
คุณสามารถใช้${INFOPLIST_PATH}สำหรับเส้นทาง plist ข้อมูล
Tomer Even

24

ใช้ Plist ของ Ben Clayton https://stackoverflow.com/a/12842530/338986

เพิ่มดังต่อไปนี้หลังจากRun script snippetCopy Bundle Resources

version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PROJECT_DIR/$INFOPLIST_FILE")
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $version ($build)" "$CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist"

การต่อท้ายCFBundleVersionนอกจากCFBundleShortVersionString. มันปล่อยเวอร์ชันดังนี้:

การเขียนถึง $CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist แทนที่จะเป็นหนึ่งใน$SRCROOTนั้นมีประโยชน์บางอย่าง

  1. ไม่ควรแก้ไขไฟล์ในสำเนาการทำงานของที่เก็บ
  2. คุณไม่จำเป็นต้องไปยังเส้นทางคดีในSettings.bundle $SRCROOTเส้นทางอาจแตกต่างกันไป

การทดสอบบน Xcode 7.3.1


1
นี่เป็นคำตอบที่ดีที่สุด IMO หากคุณเพิ่มสคริปต์ในส่วน Build, Pre-actions ของโครงร่างโครงการ ดูคำตอบของแอนดี้
Vahid Amiri

2
นี่ใช้งานได้สำหรับฉัน อย่าลืมเปลี่ยน "DefaultValue" ให้เฉพาะเจาะจงสำหรับคุณ ตัวอย่างเช่นฉันต้องการเปลี่ยนส่วนท้ายดังนั้นฉันจึงใช้ "FooterText" คุณต้องเปลี่ยนตัวเลขหลัง "PreferenceSpecifiers" เพื่อให้มีความสัมพันธ์กับรายการใน plist
Richard Witherspoon

12

ตามตัวอย่างนี่คือสคริปต์ที่ฉันใช้เพื่ออัปเดตหมายเลขเวอร์ชันบันเดิลการตั้งค่าโดยอัตโนมัติ:

#! /usr/bin/env python
import os
from AppKit import NSMutableDictionary

settings_file_path = 'Settings.bundle/Root.plist' # the relative path from the project folder to your settings bundle
settings_key = 'version_preference' # the key of your settings version

# these are used for testing only
info_path = '/Users/mrwalker/developer/My_App/Info.plist'
settings_path = '/Users/mrwalker/developer/My_App/Settings.bundle/Root.plist'

# these environment variables are set in the XCode build phase
if 'PRODUCT_SETTINGS_PATH' in os.environ.keys():
    info_path = os.environ.get('PRODUCT_SETTINGS_PATH')

if 'PROJECT_DIR' in os.environ.keys():
    settings_path = os.path.join(os.environ.get('PROJECT_DIR'), settings_file_path)

# reading info.plist file
project_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(info_path)
project_bundle_version = project_plist['CFBundleVersion']

# print 'project_bundle_version: '+project_bundle_version

# reading settings plist
settings_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(settings_path)
  for dictionary in settings_plist['PreferenceSpecifiers']:
    if 'Key' in dictionary and dictionary['Key'] == settings_key:
        dictionary['DefaultValue'] = project_bundle_version

# print repr(settings_plist)
settings_plist.writeToFile_atomically_(settings_path, True)

นี่คือ Root.plist ที่ฉันมีใน Settings.bundle:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Title</key>
            <string>About</string>
            <key>Type</key>
            <string>PSGroupSpecifier</string>
        </dict>
        <dict>
            <key>DefaultValue</key>
            <string>1.0.0.0</string>
            <key>Key</key>
            <string>version_preference</string>
            <key>Title</key>
            <string>Version</string>
            <key>Type</key>
            <string>PSTitleValueSpecifier</string>
        </dict>
    </array>
    <key>StringsTable</key>
    <string>Root</string>
</dict>
</plist>

มีประโยชน์มาก - ฉันมีปัญหาในการเรียกใช้ PlistBuddy จาก Python และฉันไม่เคยคิดที่จะใช้NSDictionary(และไม่รู้ว่ามันทำให้คุณเข้าถึงไฟล์ plist ได้ง่ายเช่นกัน)
Dov

ขอบคุณสำหรับสิ่งนี้. การปรับเปลี่ยนหนึ่งครั้ง - ตามที่คุณมีในตอนนี้การเปลี่ยนแปลงที่มาไม่ใช่ builddir ซึ่งหมายความว่าสิ่งที่คุณเห็นบนอุปกรณ์ของคุณหรือในโปรแกรมจำลองจะเป็นเวอร์ชันบิวด์หนึ่งเวอร์ชันที่อยู่เบื้องหลังเวอร์ชันบิลด์จริงเสมอ ในการแก้ไขปัญหานี้ฉันได้แก้ไขสคริปต์ของคุณให้วนซ้ำก่อนซอร์สจากนั้น builddir ด้วยเช่นกัน settings_path_build = os.path.join (os.environ.get ('TARGET_BUILD_DIR'), settings_file_path_build)
xaphod

... และฉันต่อท้าย githash:gitHash = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).rstrip()
xaphod

8

คำตอบอื่น ๆ ทำงานไม่ถูกต้องด้วยเหตุผลหนึ่ง: ขั้นตอนการสร้างสคริปต์การรันจะไม่ทำงานจนกว่าจะมีการรวมชุดการตั้งค่า ดังนั้นหากเวอร์ชัน Info.plist ของคุณเป็น 2.0.11 และคุณอัปเดตเป็น 2.0.12 จากนั้นสร้าง / เก็บถาวรโครงการของคุณชุดการตั้งค่าจะยังคงระบุว่า 2.0.11 หากคุณเปิด Root.plist บันเดิลการตั้งค่าคุณจะเห็นว่าหมายเลขเวอร์ชันไม่ได้รับการอัปเดตจนกว่าจะสิ้นสุดกระบวนการสร้าง คุณสามารถสร้างโปรเจ็กต์อีกครั้งเพื่อให้บันเดิลการตั้งค่าอัปเดตอย่างถูกต้องหรือคุณสามารถเพิ่มสคริปต์ลงในเฟสก่อนสร้างแทน ...

  • ใน XCode แก้ไข Scheme สำหรับเป้าหมายโครงการของคุณ
  • คลิกลูกศรการเปิดเผยข้อมูลในโครงการ BUILD
  • จากนั้นคลิกที่รายการ "Pre-actions"
  • คลิกเครื่องหมายบวกแล้วเลือก "New Run Script Action"
  • ตั้งค่าเชลล์เป็น / bin / sh
  • ตั้งค่า "ให้การตั้งค่าบิวด์จาก" เป็นเป้าหมายโครงการ
  • เพิ่มสคริปต์ของคุณลงในพื้นที่ข้อความ สคริปต์ต่อไปนี้ใช้ได้ผลสำหรับฉัน คุณอาจต้องแก้ไขเส้นทางเพื่อให้ตรงกับการตั้งค่าโครงการของคุณ:

    versionString = $ (/ usr / libexec / PlistBuddy -c "พิมพ์ CFBundleVersion" "$ {PROJECT_DIR} / $ {INFOPLIST_FILE}")

    / usr / libexec / PlistBuddy "$ SRCROOT / Settings.bundle / Root.plist" -c "ตั้งค่า PreferenceSpecifiers: 0: DefaultValue $ versionString"

สิ่งนี้จะเรียกใช้สคริปต์ได้อย่างถูกต้องก่อนที่บันเดิลการตั้งค่าจะถูกรวมในระหว่างกระบวนการสร้าง / เก็บถาวร หากคุณเปิดชุดการตั้งค่า Root.plist และสร้าง / เก็บถาวรโครงการของคุณตอนนี้คุณจะเห็นหมายเลขเวอร์ชันได้รับการอัปเดตเมื่อเริ่มต้นกระบวนการสร้างและชุดการตั้งค่าของคุณจะแสดงเวอร์ชันที่ถูกต้อง


ขอบคุณเฉพาะโซลูชันของคุณเท่านั้นที่แสดงเวอร์ชันบิวด์ที่ถูกต้อง โซลูชันอื่น ๆ ที่จำเป็นในการสร้างสองครั้ง
Boris Y.

สิ่งนี้ยังคงต้องใช้โครงสร้างที่สองสำหรับฉันโดยใช้ Xcode 10.0
Patrick

@Patrick บางครั้งแอปการตั้งค่า iOS จะเก็บข้อมูลเก่าไว้ หากต้องการดูการเปลี่ยนแปลงคุณต้องฆ่าและรีสตาร์ทแอปการตั้งค่า
Andy

1
BTW ฉันพบวิธีที่ง่ายกว่าในการเพิ่มสคริปต์นี้: ไปที่แท็บขั้นตอนการสร้างของเป้าหมายโครงการของคุณแล้วคลิกไอคอน "+" เลือก "New Run Script Phase" และเพิ่มรหัสสคริปต์ในนั้น นี่คือกุญแจสำคัญ: คลิกและลากสคริปต์รันใหม่ไปที่ด้านบนสุดของรายการ Build Phases ภายใต้ Target Dependencies แต่ก่อน Compile Sources สิ่งนี้จะทำงานเหมือนกับสคริปต์สร้างล่วงหน้าและหาได้ง่ายกว่า
Andy

ขอบคุณ @Andy โซลูชันของคุณในการเพิ่มแท็บขั้นตอนการสร้างทำงานได้อย่างสมบูรณ์แบบ
Patrick

8

ด้วย Xcode 11.4 คุณสามารถใช้ขั้นตอนต่อไปนี้เพื่อแสดงเวอร์ชันของแอปในชุดการตั้งค่าแอปพลิเคชันของคุณ


ชุด$(MARKETING_VERSION)และ$(CURRENT_PROJECT_VERSION)ตัวแปร

หมายเหตุ: หาก$(MARKETING_VERSION)และ$(CURRENT_PROJECT_VERSION)ตัวแปรปรากฏขึ้นสำหรับBundle version string (short)และBundle versionคีย์ใน Info.plistคุณสามารถข้ามขั้นตอนต่อไปนี้และข้ามไปยังส่วนถัดไปได้

  1. เปิดโครงการ Xcode
  2. เปิดProject Navigator ( cmd1) เลือกโปรเจ็กต์ของคุณเพื่อเปิดเผยการตั้งค่าโปรเจ็กต์ของคุณจากนั้นเลือกเป้าหมายแอพ
  3. เลือกแท็บทั่วไป
  4. ในส่วนIdentityให้เปลี่ยนเนื้อหาฟิลด์Versionเป็นค่าใหม่ (เช่น0.1.0) และเปลี่ยนเนื้อหาฟิลด์Buildเป็นค่าใหม่ (เช่น12) การเปลี่ยนแปลง 2 รายการนี้จะสร้าง$(MARKETING_VERSION)และ$(CURRENT_PROJECT_VERSION)ตัวแปรในไฟล์Info.plist

สร้างและกำหนดค่าชุดการตั้งค่า

  1. ในProject Navigatorเลือกโครงการของคุณ
  2. เลือกไฟล์ > ใหม่ > ไฟล์… ( cmdN)
  3. เลือกแท็บiOS
  4. เลือกการตั้งค่า Bundleในทรัพยากรส่วนแล้วคลิกถัดไปและสร้าง
  5. เลือกRoot.plistและเปิดเป็นซอร์สโค้ด แทนที่เนื้อหาด้วยรหัสด้านล่าง:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>DefaultValue</key>
            <string></string>
            <key>Key</key>
            <string>version_preference</string>
            <key>Title</key>
            <string>Version</string>
            <key>Type</key>
            <string>PSTitleValueSpecifier</string>
        </dict>
    </array>
    <key>StringsTable</key>
    <string>Root</string>
</dict>
</plist>

เพิ่มสคริปต์การเรียกใช้

  1. ในProject Navigatorเลือกโครงการของคุณ
  2. เลือกเป้าหมายแอป
  3. เลือกแท็บขั้นตอนการสร้าง
  4. คลิก+ > ใหม่เรียกใช้เฟสสคริปต์
  5. ลากและวางขั้นตอนอยู่ที่ไหนสักแห่งใหม่เหนือCopy Bundle ทรัพยากรส่วน ด้วยวิธีนี้สคริปต์จะถูกดำเนินการก่อนที่จะรวบรวมแอปพลิเคชัน
  6. เปิดเฟสRun Script ที่เพิ่มใหม่และเพิ่มสคริปต์ต่อไปนี้:
version="$MARKETING_VERSION"
build="$CURRENT_PROJECT_VERSION"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"

เปิดแอป

  1. เรียกใช้ผลิตภัณฑ์ ( cmdR) บนอุปกรณ์หรือโปรแกรมจำลอง
  2. บนอุปกรณ์หรือเครื่องจำลองเมื่อเปิดแอปแล้วให้เปิดแอปการตั้งค่าและเลือกแอปของคุณในรายการแอปของบุคคลที่สาม ควรแสดงเวอร์ชันของแอปดังที่แสดงด้านล่าง:


แหล่งที่มา


สิ่งนี้ทำให้ฉันเกิดข้อผิดพลาดSet: Entry, "PreferenceSpecifiers:0:DefaultValue", Does Not Exist
Jordan H

2
สิ่งนี้ได้ผลสำหรับฉัน:/usr/libexec/PlistBuddy "$SRCROOT/AppName/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:0:DefaultValue $version"
Jordan H

ขอบคุณ. นี่คือโลกสำหรับฉัน แต่ของฉันใช้ชื่อว่า Settings-Watch.bundle และลบ($build)
Kurt Lane

สุดยอด! สำหรับฉันความช่วยเหลือหลักที่นี่คือการใช้คำตอบของ @Ben Clayton แต่แก้ไขสคริปต์การเรียกใช้เพื่อใช้ $ MARKETING_VERSION และ $ CURRENT_PROJECT_VERSION ตามที่คุณชี้ให้เห็น สิ่งนี้จำเป็นสำหรับฉันเพราะตอนนี้หมายเลขเวอร์ชันเหล่านั้นไม่ได้ถูกเก็บไว้โดยตรงใน Info.plist ดังนั้นการอ่าน Info.plist ในสคริปต์การเรียกใช้จึงไม่เป็นประโยชน์ในกรณีนี้ (ซึ่งเป็นค่าเริ่มต้น Xcode ในขณะนี้)
Mete

โอ้ยังมีรายละเอียดเล็กน้อย แต่สคริปต์การรันของคุณกำหนดนิยามใหม่โดยไม่จำเป็น$MARKETING_VERSION-> $version- คุณสามารถใส่$MARKETING_VERSIONคำสั่ง PlistBuddy ได้โดยตรงทำให้เป็นซับเดียว
Mete

3

ฉันจัดการเพื่อทำสิ่งที่ฉันต้องการโดยใช้ porject โอเพนซอร์ส pListcompiler ( http://sourceforge.net/projects/plistcompiler )

  1. การใช้คอมไพเลอร์นี้คุณสามารถเขียนไฟล์คุณสมบัติในไฟล์. plc โดยใช้รูปแบบต่อไปนี้:

    plist {
        dictionary {
            key "StringsTable" value string "Root"
            key "PreferenceSpecifiers" value array [
                dictionary {
                    key "Type" value string "PSGroupSpecifier"
                    key "Title" value string "AboutSection"
                }
                dictionary {
                    key "Type" value string "PSTitleValueSpecifier"
                    key "Title" value string "Version"
                    key "Key" value string "version"
                    key "DefaultValue" value string "VersionValue"
                    key "Values" value array [
                        string "VersionValue"
                    ]
                    key "Titles" value array [
                        string "r" kRevisionNumber
                    ]
                }
            ]
        }
    }
    
  2. ฉันได้ทำงานที่กำหนดเองสคริปต์สร้างเฟสที่แยกการแก้ไขพื้นที่เก็บข้อมูลของฉันไปยังแฟ้ม .h ตามที่อธิบายไว้โดยแบรด-Larson ที่นี่

  3. ไฟล์ plc สามารถมีคำสั่งของตัวประมวลผลล่วงหน้าเช่น #define, #message, #if, #elif, #include, #warning, #ifdef, #else, #pragma, #error, #ifndef, #endif, ตัวแปรสภาพแวดล้อม xcode ดังนั้นฉันจึงสามารถอ้างอิงตัวแปร kRevisionNumber โดยเพิ่มคำสั่งต่อไปนี้

    #include "Revision.h"
    
  4. ฉันยังเพิ่มเฟสการสร้างสคริปต์ที่กำหนดเองให้กับเป้าหมาย xcode ของฉันเพื่อเรียกใช้ plcompiler ทุกครั้งที่โปรเจ็กต์กำลังสร้าง

    /usr/local/plistcompiler0.6/plcompile -dest Settings.bundle -o Root.plist Settings.plc
    

และนั่นมัน!


ดูเหมือนว่าจะต้องทำงานมากเพียงเพื่อแทนที่ค่าเดียวในไฟล์ plist ... เป็นแนวคิดที่ยอดเยี่ยมที่จะสามารถเข้าถึงตัวแปรเมื่อสร้าง plist แต่จะใช้เครื่องมือสร้างไฟล์ plist ได้ง่ายกว่ามาก ฉันอธิบาย PlistBuddy ในคำตอบของฉัน - ลองดูสิ!
Quinn Taylor

3

ตัวอย่างการทำงานของฉันอ้างอิงจากคำตอบของ @Ben Clayton และความคิดเห็นของ @Luis Ascorbe และ @Vahid Amiri:

หมายเหตุ: วิธีนี้แก้ไขไฟล์Settings.bundle / Root.plistในสำเนาที่เก็บข้อมูลที่ใช้งานได้

  1. เพิ่มบันเดิลการตั้งค่าไปยังรูทโปรเจ็กต์ของคุณ อย่าเปลี่ยนชื่อ

  2. เปิด Settings.bundle / Root.plist เป็น SourceCode

    แทนที่เนื้อหาด้วย:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>PreferenceSpecifiers</key>
        <array>
            <dict>
                <key>DefaultValue</key>
                <string></string>
                <key>Key</key>
                <string>version_preference</string>
                <key>Title</key>
                <string>Version</string>
                <key>Type</key>
                <string>PSTitleValueSpecifier</string>
            </dict>
        </array>
        <key>StringsTable</key>
        <string>Root</string>
    </dict>
    </plist>
    
  3. เพิ่มสคริปต์ต่อไปนี้ในส่วน Build, Pre-actions ของโครงร่างโครงการ (เป้าหมาย)

    version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
    build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PROJECT_DIR/$INFOPLIST_FILE")
    
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"
    
  4. สร้างและรันโครงร่างปัจจุบัน


2

คำตอบข้างต้นไม่ได้ผลสำหรับฉันดังนั้นฉันจึงสร้างสคริปต์ที่กำหนดเองของฉัน

สิ่งนี้จะอัพเดตรายการจาก Root.plist แบบไดนามิก

ใช้สคริปต์รันด้านล่าง ทำงานไม่ดีอย่างแน่นอนได้รับการตรวจสอบใน xcode 10.3

"var buildVersion" คือเวอร์ชันที่จะแสดงในชื่อ

และชื่อตัวระบุคือ "var version" ด้านล่างสำหรับชื่อใน settings.bundle Root.plist

cd "${BUILT_PRODUCTS_DIR}"

#set version name to your title identifier's string from settings.bundle
var version = "Version"

#this will be the text displayed in title
longVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}")
shortVersion=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${TARGET_BUILD_DIR}/${INFOPLIST_PATH})
buildVersion="$shortVersion.$longVersion"

path="${WRAPPER_NAME}/Settings.bundle/Root.plist"

settingsCnt=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ${path} | grep "Dict"|wc -l`

for (( idx=0; idx<$settingsCnt; idx++ ))
do
#echo "Welcome $idx times"
val=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:Key" ${path}`
#echo $val

#if ( "$val" == "Version" )
if [ $val == "Version" ]
then
#echo "the index of the entry whose 'Key' is 'version' is $idx."

# now set it
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:${idx}:DefaultValue $buildVersion" $path

# just to be sure that it worked
ver=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:DefaultValue" $path`
#echo 'PreferenceSpecifiers:$idx:DefaultValue set to: ' $ver

fi

done

ตัวอย่างรายการใน Root.plist

    <dict>
        <key>Type</key>
        <string>PSTitleValueSpecifier</string>
        <key>Title</key>
        <string>Version</string>
        <key>DefaultValue</key>
        <string>We Rock</string>
        <key>Key</key>
        <string>Version</string>
    </dict>

ตัวอย่างการทำงานรายการ Root.plist


1

ฉันเชื่อว่าคุณสามารถทำได้โดยใช้วิธีที่คล้ายกับที่ฉันอธิบายไว้ในคำตอบนี้ (อ้างอิงจากโพสต์นี้ )

ขั้นแรกคุณสามารถทำให้ VersionValue เป็นตัวแปรภายใน Xcode โดยเปลี่ยนชื่อเป็น $ {VERSIONVALUE} สร้างไฟล์ชื่อ versionvalue.xcconfig และเพิ่มลงในโปรเจ็กต์ของคุณ ไปที่เป้าหมายแอปพลิเคชันของคุณและไปที่การตั้งค่าสร้างสำหรับเป้าหมายนั้น ฉันเชื่อว่าคุณต้องเพิ่ม VERSIONVALUE เป็นการตั้งค่าการสร้างที่ผู้ใช้กำหนดเอง ที่มุมล่างขวาของหน้าต่างนั้นให้เปลี่ยนค่า Based On เป็น "versionvalue"

สุดท้ายไปที่เป้าหมายของคุณและสร้างเฟสการสร้าง Run Script ตรวจสอบว่ารันสคริปต์เฟสและวางในสคริปต์ของคุณภายในฟิลด์ข้อความสคริปต์ ตัวอย่างเช่นสคริปต์ของฉันที่จะแท็กการตั้งค่า BUILD_NUMBER ของฉันด้วยบิลด์การโค่นล้มปัจจุบันมีดังนี้:

REV=`/usr/bin/svnversion -nc ${PROJECT_DIR} | /usr/bin/sed -e 's/^[^:]*://;s/[A-Za-z]//'`
echo "BUILD_NUMBER = $REV" > ${PROJECT_DIR}/buildnumber.xcconfig

สิ่งนี้ควรใช้เคล็ดลับในการแทนที่ตัวแปรเมื่อค่าเหล่านี้เปลี่ยนแปลงภายในโครงการของคุณ


ใช้งานได้ถ้าฉันต้องการฝังหมายเลขเวอร์ชันลงในไฟล์ Info.plist แต่ฉันไม่สามารถทำให้มันใช้งานได้กับไฟล์ plist อื่น ๆ เช่นไฟล์ Root.plist ที่อยู่ใน Settings.bundle มีการตั้งค่าการสร้างที่ฉันสามารถใช้เพื่อเปิดใช้งานสิ่งนี้ได้หรือไม่
Panagiotis Korros

0

สำหรับฉันนี่เป็นวิธีแก้ปัญหาที่ง่ายที่สุด:

เพิ่มเฟสการสร้างสคริปต์ใหม่ก่อนขั้นตอนคัดลอกทรัพยากรบันเดิล

เปลือก: /usr/bin/env python

เนื้อหา:

#! /usr/bin/env python
import os
from AppKit import NSMutableDictionary

# Key to replace
settings_key = 'version_preference' # the key of your settings version

# File path
settings_path = os.environ.get('SRCROOT') + "/TheBeautifulNameOfYourOwnApp/Settings.bundle/Root.plist"

# Composing version string
version_string = os.environ.get('MARKETING_VERSION') + " (" + os.environ.get('CURRENT_PROJECT_VERSION') + ")"

# Reading settings plist
settings_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(settings_path)
for dictionary in settings_plist['PreferenceSpecifiers']:
    if 'Key' in dictionary and dictionary['Key'] == settings_key:
        dictionary['DefaultValue'] = version_string

# Save new settings
settings_plist.writeToFile_atomically_(settings_path, True)

0

นี่คือตัวแปรที่ฉันต้องใช้สำหรับโปรเจ็กต์ที่รวดเร็วด้วย Xcode 12.2

version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
build="$CURRENT_PROJECT_VERSION"

/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:FooterText Version $version" "$CODESIGNING_FOLDER_PATH/Settings.bundle/ServerURLSettings.plist"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:FooterText Version $version($build)" "$CODESIGNING_FOLDER_PATH/Settings.bundle/DeveloperSettings.plist"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.