【XCode中变更 resource文件后,需要重新编译才能正确识别更新】问题的解决方案
2014-05-26 14:23
435 查看
转自:
http://majicjungle.com/blog/123/
[Update: Joachim Bengtsson provided a much much easier way to make Xcode notice new changes, the new simpler script is now included in the instructions.
Thanks Joachim!]
If you don’t see a problem with the way that Xcode manages ‘Resources’ (images, sounds etc.) then you probably have nothing to learn from this article. Xcode usually manages just fine if you only have a small project, with limited changes to resources, and
only a couple of applications and one person ever modifying them.
But, Xcode’s directory management is broken enough to become really annoying in larger projects. I’ll explain why, as well as offer a solution. This article focuses on iPhone development. A very similar problem exists when developing for Mac OS X, with a similar
but simpler solution, but I won’t go into it here.
Usually when you want to have an image or sound or any other resource in your iPhone application, you add it to Xcode, it is silently added to the ‘Copy Bundle Resources’ build phase, it might get converted or stripped back (pngs get quite heavily modified)
and then gets copied into the app bundle. You can then access it at runtime with NSBundle methods. Easy.
The problem only shows up when you want to have some kind of directory structure on disk. There are many reasons why you might want to do this. In a game, perhaps your levels are themselves directories. Perhaps you want to switch between different versions
of resources, or simply like to be a little more organized than having all of your resources at one level in one big-ass directory.
Xcode offers two options when you add a directory to the project. You can either add it as the default yellow ‘group’ or as a blue ‘folder reference’. The problem is, that both have pretty major limitations (and bugs).
The group option will never notice if the directory contents are added or removed. Every time you add or remove a file or directory in the file system, you will also have to change it in Xcode. Also, the directory structure is lost when it’s copied to the iphone
app, and so inside your app bundle is just a big list of all your resources in the base directory. As a result of this, duplicate filenames become an issue. If any files within your directory structure on disk contain the same filename, the build process silently
screws everything up. It appears to be ‘first in wins’, with only one of the resources making it into the app bundle. So it’s no good if you have a bunch of different level packages each containing a different ‘Terrain.png’ file.
Which means you have to use the other option, blue ‘folder references’. This should be the better option of the two no matter what you are doing. When you add or remove files, it usually gets noticed. You can safely have duplicate names, and you don’t
have to repeat your moving/renaming/adding etc. in Xcode. But the problem is, that when you externally change a file within a folder reference, Xcode doesn’t notice. So every time you modify an image file, you do a new build, fire it up, and think ‘It looks
the same as before’. Thats because it is the same as before. You need to do a clean build (or delete the app) to force Xcode to copy the resource directory structure again.
This is a pain, and if you’re like me, you will nearly always forget, wasting large amounts of time slowly making an image darker, but it still looks too light! Half an hour later realizing it never got copied to the app bundle.
So. A solution.
I made a top level directory I called ‘GameResources’ inside of which are all the app’s resource files and sub-directories. It is important not to call this directory ‘Resources’, as it seems to confuse Xcode into giving a lot of ‘Application is already installed’
errors.
1) Add your single resource directory (named anything but ‘Resources’) to your project in the Resources section as a blue ‘Folder Reference’
2) Right click on your app target, select Add->New Build Phase->New Run Script Build Phase
3) In the resulting ‘Info’ window, change the shell to /bin/tcsh and copy and past the script below into the ‘Script’ text view.
Script:
How it should look:
4) Change the directory to your resource directory. In my case it is ‘GameResources’, a couple of levels above the source directory, but usually if your resources are located in the same directory as your Xcode project it would be simply ${SRCROOT}/MyResources
5) Change the order of the build phases (by dragging the Run Script one you just created) so that it is run just after the Copy Bundle Resources build phase. This may not be necessary, but it feels right. Leave the ‘Copy Bundle Resources’ build phase alone,
it doesn’t do any harm, and is needed for distribution builds.
6) Before this, you probably used [[NSBundle mainBundle] resourcePath] or pathForResource:. These won’t work anymore, as all your resources are now inside ‘GameResources’ or whatever. [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@”GameResources”]
or similar will need to be used instead.
A couple of notes – You can edit the script by double clicking the ‘Run Script’ build phase, it’s not entirely obvious. And if you have renamed your debug configuration you probably need to modify the if statement at the top of the script.
And finally, this might not work at all for any number of reasons. I probably won’t be able to help you with any problems, but hopefully it will save someone some time and frustration.
Maybe someone at Apple might even see this, notice the hoops we have to jump through, and be more inclined to fix the damn thing properly!
http://majicjungle.com/blog/123/
Xcode resource groups and folder references when building for iPhone
Written by David Frampton @ 7:17 am, May 2, 2009
[Update: Joachim Bengtsson provided a much much easier way to make Xcode notice new changes, the new simpler script is now included in the instructions.Thanks Joachim!]
If you don’t see a problem with the way that Xcode manages ‘Resources’ (images, sounds etc.) then you probably have nothing to learn from this article. Xcode usually manages just fine if you only have a small project, with limited changes to resources, and
only a couple of applications and one person ever modifying them.
But, Xcode’s directory management is broken enough to become really annoying in larger projects. I’ll explain why, as well as offer a solution. This article focuses on iPhone development. A very similar problem exists when developing for Mac OS X, with a similar
but simpler solution, but I won’t go into it here.
Usually when you want to have an image or sound or any other resource in your iPhone application, you add it to Xcode, it is silently added to the ‘Copy Bundle Resources’ build phase, it might get converted or stripped back (pngs get quite heavily modified)
and then gets copied into the app bundle. You can then access it at runtime with NSBundle methods. Easy.
The problem only shows up when you want to have some kind of directory structure on disk. There are many reasons why you might want to do this. In a game, perhaps your levels are themselves directories. Perhaps you want to switch between different versions
of resources, or simply like to be a little more organized than having all of your resources at one level in one big-ass directory.
Xcode offers two options when you add a directory to the project. You can either add it as the default yellow ‘group’ or as a blue ‘folder reference’. The problem is, that both have pretty major limitations (and bugs).
The group option will never notice if the directory contents are added or removed. Every time you add or remove a file or directory in the file system, you will also have to change it in Xcode. Also, the directory structure is lost when it’s copied to the iphone
app, and so inside your app bundle is just a big list of all your resources in the base directory. As a result of this, duplicate filenames become an issue. If any files within your directory structure on disk contain the same filename, the build process silently
screws everything up. It appears to be ‘first in wins’, with only one of the resources making it into the app bundle. So it’s no good if you have a bunch of different level packages each containing a different ‘Terrain.png’ file.
Which means you have to use the other option, blue ‘folder references’. This should be the better option of the two no matter what you are doing. When you add or remove files, it usually gets noticed. You can safely have duplicate names, and you don’t
have to repeat your moving/renaming/adding etc. in Xcode. But the problem is, that when you externally change a file within a folder reference, Xcode doesn’t notice. So every time you modify an image file, you do a new build, fire it up, and think ‘It looks
the same as before’. Thats because it is the same as before. You need to do a clean build (or delete the app) to force Xcode to copy the resource directory structure again.
This is a pain, and if you’re like me, you will nearly always forget, wasting large amounts of time slowly making an image darker, but it still looks too light! Half an hour later realizing it never got copied to the app bundle.
So. A solution.
I made a top level directory I called ‘GameResources’ inside of which are all the app’s resource files and sub-directories. It is important not to call this directory ‘Resources’, as it seems to confuse Xcode into giving a lot of ‘Application is already installed’
errors.
1) Add your single resource directory (named anything but ‘Resources’) to your project in the Resources section as a blue ‘Folder Reference’
2) Right click on your app target, select Add->New Build Phase->New Run Script Build Phase
3) In the resulting ‘Info’ window, change the shell to /bin/tcsh and copy and past the script below into the ‘Script’ text view.
Script:
touch -cm ${SRCROOT}/../../GameResources
How it should look:
4) Change the directory to your resource directory. In my case it is ‘GameResources’, a couple of levels above the source directory, but usually if your resources are located in the same directory as your Xcode project it would be simply ${SRCROOT}/MyResources
5) Change the order of the build phases (by dragging the Run Script one you just created) so that it is run just after the Copy Bundle Resources build phase. This may not be necessary, but it feels right. Leave the ‘Copy Bundle Resources’ build phase alone,
it doesn’t do any harm, and is needed for distribution builds.
6) Before this, you probably used [[NSBundle mainBundle] resourcePath] or pathForResource:. These won’t work anymore, as all your resources are now inside ‘GameResources’ or whatever. [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@”GameResources”]
or similar will need to be used instead.
A couple of notes – You can edit the script by double clicking the ‘Run Script’ build phase, it’s not entirely obvious. And if you have renamed your debug configuration you probably need to modify the if statement at the top of the script.
And finally, this might not work at all for any number of reasons. I probably won’t be able to help you with any problems, but hopefully it will save someone some time and frustration.
Maybe someone at Apple might even see this, notice the hoops we have to jump through, and be more inclined to fix the damn thing properly!
相关文章推荐
- 黑莓ECLIPSE3.5开发环境不识别资源文件导致编译不通过解决方案附文件(系统语言问题)
- 待续。makefile关于文件修改时间确定是否需要重新编译的正确书写格式
- 更新Xcode6.0.1之后,编译出现Use of undeclared identifier 'GL_BGRA_EXT'问题及解决方案
- Xcode更新或者重新安装导致插件无效问题的解决方案
- Mac上的应用,例如Xcode需要输入原始下载账号才能更新问题
- RK3288 kernel 编译 resource.img 时 .dtb 文件无法识别问题
- VMware Workstation 运行出现“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”解决方案
- Tomcat重新发布项目后配置文件不更新的问题
- 安装sql2000时提示“某个文件被挂起,需要重新启动才能安装”的问题
- Android ADT更新后无法编译生成R.java的问题解决方案
- xcode 每次 全部 重新 编译 的问题
- 关于mp4文件在IE6-IE8里需要完全缓冲完才能播放的问题
- [WPF]多Resource文件的相互引用与合并问题及其解决方案
- Resource文件的相互引用与合并问题及其解决方案
- VMware 运行出现“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”解决方案
- vs2008编译程序"由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题"
- VMware Workstation 运行出现“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”解决方案
- SWFUpload与CI不能正确上传识别文件MIME类型解决方案
- .NET2003安裝出现一直重启问题和SQL 2000安装出现“以前进行的程序安装创建了挂起的文件操作。运行程序之前,必须重新起动计算机。”~[解决方案]
- ubuntu opera问题解决--E: 软件包 opera 需要重新安装,但是我无法找到相应的安装文件。