跳至主要内容

Settings Bundles Management in Xcode

 原文链接


What is a Settings bundle? A Settings bundle is a special kind of bundle provided by Apple to allow developers to add their app preferences into the iOS Settings app.

With the current state of iOS app development, almost always we will have multiple build configurations such as debug, beta, and release. Or we might even have multiple app targets within an Xcode project for various purposes.

With the situation mentioned above, how should one go about loading the desired Settings bundle for the respective build configuration?

In this article, let’s look into how we should manage the Settings bundles in the following situations:

  1. Load Settings bundle only for debug configuration.
  2. Load different Settings bundles for debug and release configuration.
  3. Load different Settings bundles for different app targets.

The Concept Behind Settings Bundle

Before we start getting into Settings bundles management, let’s have a quick look at the concept behind Settings bundle.

Settings bundle is considered as resources of the app bundle. Every time when you build your project, Xcode will copy the Settings bundle into the app bundle and the iOS Settings app will display the app preferences based on the Settings bundle.

The following diagram illustrates the workflow behind the scene when you build your Xcode project.

The concept behind settings bundle in iOS
The concept behind settings bundle

By understanding the concept behind Settings bundle, you should be able to follow along with this tutorial without any problem.


Load Settings Bundle Only for Debug Configuration

Sometimes you might want to expose certain app preferences in the iOS Settings app just for testing or debugging purposes. However, this kind of app preferences should not be accessible to normal users.

In this kind of situation, you can include all those special app preferences into the Settings bundle and make the Settings bundle only available for debug configuration. To achieve that, you can run a shell script at the end of the Xcode build phases to delete the Settings bundle from the app bundle during a release build.

Adding Shell Script

Adding a shell script in the Xcode build phase is pretty easy. You can start by selecting your project in the project navigator. Open the “Build Phases” tab and click the “+” sign to add a new run script phase.

Adding shell script in Xcode
Adding shell script

Copy and paste the following shell script into the scripting box so that it will run every time when Xcode builds your project.

BUILD_APP_DIR="$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app"

if [ $CONFIGURATION == "Release" ]; then
    rm -rf "$BUILD_APP_DIR/Settings.bundle"
fi

Basically what the above shell script does is to remove the Settings bundle (Settings.bundle) from the app bundle when the project is built with configuration named “Release”.

At this point, you might wonder where do these build configurations being defined. Head over to the project info tab, there you should see the “Configurations” section where it lists out all the build configurations available.

List of Xcode configuration
List of Xcode build configurations

Switching Build Configuration for Testing

By default, when you build and run (⌘R) a project, the project will be built using the “Debug” configuration. Go ahead and run the project using the “Debug” configuration, you should see the Settings app showing all the app preferences defined in the Settings bundle.

Displaying app preferences in iOS Settings app
Displaying app preferences in iOS Settings app

Next, let’s switch the build configuration to “Release” by editing the app target scheme.

Change build configuration in Xcode
Change build configuration

After changing the build configuration to “Release”, build and run your project again. This time you should not see any app preferences being added to the Settings app because the shell script has removed the Settings bundle from the app bundle.

Shell Script Debugging

If the shell script is not behaving as you expected, most probably the shell script is not getting the correct app bundle path. In this kind of situation, for debugging purposes, you can print out the BUILD_APP_DIR using the echo command.

Using echo in shell script
Using echo in shell script

You can check the printed out BUILD_APP_DIR value at Xcode report navigator.

Shell script echo result in Xcode
Shell script echo result

Lastly, if you found that the shell script is not taking effect even though you have updated it, cleaning the build folder (⇧⌘K) then rebuild the project should do the trick.


Load Different Settings Bundles for Debug and Release Configuration

Similar to the situation mentioned in the previous section, you want to enable certain app preferences just for debugging purposes. However, this time you do have some other end users related app preferences that you want to include in the release build.

In this kind of situation, you will have to create 2 Settings bundles, remove them from the “Copy Bundle Resources” build phase and then run a shell script to manually copy the respective Settings bundle to the app bundle.

Let’s say you have created 2 Settings bundles for your project as shown in the image below:

Settings bundles for debug and release build configuration in Xcode
Settings bundles for debug and release build configuration

Head over to the app target build phases tab and remove the 2 Settings bundles from the “Copy Bundle Resources” list.

Remove Settings bundle from bundle resources in Xcode
Remove Settings bundle from bundle resources

Lastly, copy the following shell script and paste it into the scripting box.

BUNDLE_DIR="$PROJECT_DIR/$PRODUCT_NAME/Settings Bundles"
BUILD_APP_DIR="$BUILT_PRODUCTS_DIR/$PRODUCT_NAME.app"

if [ $CONFIGURATION == "Release" ]; then
    # Copy Settings bundle in "Release" folder into the app bundle
    cp -rf "$BUNDLE_DIR/Release/Settings.bundle" "$BUILD_APP_DIR/Settings.bundle"
else
    # Copy Settings bundle in "Debug" folder into the app bundle
    cp -rf "$BUNDLE_DIR/Debug/Settings.bundle" "$BUILD_APP_DIR/Settings.bundle"
fi

Now, Go ahead and run your project in “Debug” or “Release” configuration and see the app preferences in the Settings app change accordingly.

Something to Take Note

The Settings bundle must be named as “Settings.bundle” in the app bundle, any other naming will not work and you won’t see your app being listed in the iOS Settings app.

If you bump into the following compiler error, most probably the path defined in the shell script is not pointing to the Settings bundle.

Command PhaseScriptExecution failed with a nonzero exit code
Compiler error when copy Settings bundle with shell script in Xcode
Compiler error when copy Settings bundle with shell script

What you can do is to print out the respective path using echo and fix the problem accordingly.


Load Different Settings Bundles for Different App Targets

In the last section of this article, let’s look at how to manage multiple Settings bundles in a multiple app targets environment.

Let’s say you have an Xcode project with 2 app targets (Paid and Free). On top of that, each app target will have its own Settings bundle.

In order to let Xcode know which Settings bundle belongs to which target, you just need to set the Settings.bundle target membership correctly, then you are good to go.

Assign Settings bundle to app target (free version) in Xcode
Assign Settings bundle to app target (free version)
Assign Settings bundle to app target (paid version) in Xcode
Assign Settings bundle to app target (paid version)

That’s it for managing Settings bundles in a multiple app targets environment. No shell script is required. 🥳


Wrapping Up

Managing Settings bundles is an easy task once you have understood how Xcode handles them in different kinds of environments. Just remember:

  • There can only be 1 Settings bundle in an app bundle.
  • Settings bundle must be named as “Settings.bundle” in the app bundle in order for it to work.

Further Readings

If you would like to learn more about using Settings bundle, you can check out this official documentation from Apple.

Implementing an iOS Settings Bundle

Besides, feel free to check out my some other articles related to Xcode.


I hope you find this article helpful. What other situations do you think that this article should cover? Let me know in the comment section below or you can reach out to me on Twitter.

Thanks for reading. 🧑🏻‍💻

评论

此博客中的热门博文

Resolving errSecInternalComponent errors during code signing

原文链接 One code signing issue I commonly see, both here on DevForums and in my Day Job™ with DTS, is that the codesign command fails with errSecInternalComponent. This issue crops up in a wide variety of circumstances and the correct fix depends on the specific problem. This post is my attempt to clarify the potential causes of this error and help folks resolve it. If you have any questions or comments about this, please start a new thread, tagging it with Code Signing so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving errSecInternalComponent errors during code signing In some circumstances the codesign command might fail with the error errSecInternalComponent. For example: % codesign -s "Apple Development" "MyTrue" MyTrue: errSecInternalComponent This typically affects folks who are signing code in a nonstandard environm...

iOS:检测使用VPN或Proxy

参考链接: https://www.jianshu.com/p/c3b950dbf86a https://gist.github.com/PramodJoshi/4faad4c91f7dcb4eb9b06be8390c01db http://noodlecode.net/2018/04/check-if-ios-app-is-connected-to-vpn 第一种方法 需要导入框架CFNetwork 然后,这个方法是mrc的:需要添加-fno-objc-arc的flag 代码如下: + ( BOOL )getProxyStatus { NSDictionary *proxySettings = NSMakeCollectable ([( NSDictionary *) CFNetworkCopySystemProxySettings () autorelease]); NSArray *proxies = NSMakeCollectable ([( NSArray *) CFNetworkCopyProxiesForURL (( CFURLRef )[ NSURL URLWithString: @"http://www.google.com" ], ( CFDictionaryRef )proxySettings) autorelease]); NSDictionary *settings = [proxies objectAtIndex: 0 ]; NSLog ( @"host=%@" , [settings objectForKey:( NSString *)kCFProxyHostNameKey]); NSLog ( @"port=%@" , [settings objectForKey:( NSString *)kCFProxyPortNumberKey]); NSLog ( @"type=%@" , [settings objectForKey:( NSString *)kCFProxyTypeKey]); if ([[settings object...

去广告DNS设置,国内ADGuard DNS方案,手机电脑iOS去广告,保护隐私

 原文链接 之前分享过使用mac系统搭建adguard home,这几个月用下来零零散散基本上也被弃用了。主要原因是因为需要保持电脑一直开机。但是我的电脑是笔记本,存在移动各个地域的情况,也就是说只能够屏蔽电脑自身,对于手机而言不太现实。今天偶然发现dnspod推出了高级版的公共解析。dnspod背靠腾讯云,肯定是合法合规的公共解析服务,这个高级版用起来不错。 国内自己搭建解析服务是违法行为,所以这也是为什么使用dnspod的原因。 后台截图 开始使用 首先我们先进入dnspod的公共解析页面,点击开始使用。 专业版公共解析 dnspod会提供几种预设,我们选择「开发者」即可 开发者 然后你就成功的申请到自己个人使用的dns了! 更新拦截规则 我们可以将常见的广告过滤规则加入到dns中。我们在顶部选项卡中选择「拦截规则」。 拦截规则设置 打开adguard adguard 绑定iOS设备 推荐使用描述文件的方式,删除配置时删除描述文件即可。 描述文件 绑定macOS 推荐使用描述文件的方式,删除配置时删除描述文件即可。 描述文件 mac需要在「系统偏好设置」的「网络」中查看是否正在运行。 代理 如果没有运行需要点击「···」来启动服务。 启动服务 绑定路由器 找到自己路由器的DHCP设置,修改dns,然后记得绑定自己的ip。 修改dns 绑定ip 费用 目前有300万次/月的免费额度,但没有超出之后的价格。300万次一个人比较难用完,可以放心使用。 我个人使用iOS设备两台、智能家居、电脑两台,日均请求数大致2万/日。 判断是否搭建成功 可以通过查看日志的方式,日志大概有半小时到一小时的延迟,请耐心等待。