Since I upgraded to Xcode 4.5 I've found that it's automatically removing a section of each xib file I visit. Here is the section:
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<real value="1536" key="NS.object.0"/>
</object>
I can almost live with this, but when I go visit the file again I find there are even more 'auto' changes. They are more varied and harder to characterize so I won't include examples unless I really need to.
I don't understand what's going on here. I'm looking for one of two answers:
Is there some way to disable this?
Why is this happening and is there some way to force Xcode to apply these changes to all xib files so I can be done with this?
I would feel a lot better if I just understood what the heck is going on and why.
From what I've seen of this, Xcode will automatically reformat nibs, adding/removing from the .xib files as needed. Nothing seems to be functionally different for my purposes when I've had this happen.
Just for SEO, I'll bring this up, as this is very relevant when tracking changes in version control, such as Git. Every time I open old .xib files in Xcode (I'm using 5.0), they are automatically changed and it shows up in my Git client's diff tool.
TRY THIS:
*(If you are not using Git or some version control, set up a repo for the project to test this.)
See if there are any remaining unmodified .xibs you can open without modifying them.
Select/View it, but don't change anything.
Now select/view a different file in the project navigator. If an "M" shows up next to the .xib, rebuild your project and verify that it's behavior is the same.
If you want to ignore these, for version control reasons, just be sure not to stage/commit them if you're not intentionally making any changes to them.
If you want to "undo" the automatically changed file(s):
Right click on the file in the project navigator.
Go to "Source Control" >>> "Discard Changes..."
OR, discard them via Git or your version control tool of choice.
there is a way to disable this, but it is not without its own problems (listed below). You can show the xib file in Finder, Get Info on the file, and then under General, select Locked.
Problem 1: If you use source control, like most people, you won't be able to checkout an earlier commit or reset your branch to an earlier commit, until you unlock all the files that will be changed by the operation.
Problem 2: Now, every time you view the file in IB, a popup slides down from the top of the xCode window, with the title
“MBPreDeliveryComplete.xib” is locked for editing and you may not be able to save your changes. Do you want to unlock it?
And this message:
“MBPreDeliveryComplete.xib” is currently locked because it is marked as ‘Locked’ in the Finder.
With buttons giving the option of unlocking or not unlocking the file. Of course you can elect not to unlock the file, unless you actually intend to make changes.
Related
We are coding for senior project. But when I pull project on Xcode, main.storyboard gives an error like in picture. I discarded all changes and cleaned my project, but it did not work. Half of project is on my friend computer, half of is on mine. How can I fix this GitHub error and how can we compound this parts ? Ps : I have backup of my project in another folder.
Storyboards are .xml files. The issue you have recently happened to me after I didn't properly resolve GitHub merge conflicts. When you don't edit the stuff in the <<<<< >>>>>> brackets properly, inside the file that has merge conflicts, you can generate the ID conflicts.
You either have to open the xml file of the storyboard with Xcode itself (or with a Texteditor like Sublime) and fix it manually (if you know what you are doing and where the duplicate elements are, as the file xml-structure is quite complex). The BEST way (especially since you have a backup) would be to go inside the project folder and replace the storyboard file with the old one. You will loose changes made since the backup, but if you commit frequently, it should not be too far behind.
EDIT: If the rest of the stuff you merged relies on a newer version of the storyboard (e.g. IBOutlets or IBActions), you will have to recreate those assets in the storyboard and re-connect them to your code.
Another route instead of replacing the storyboard file would be to do a git hard reset to your last commit before the merge and then attempt to merge again. At that point try to resolve the storyboard conflicts better, which may be very difficult. Don't worry, storyboard merge conflicts are a big pain to every developer. If nothing helps, resetting by replacing the file above should always work.
GENERAL RULE: Try to use multiple storyboards for your viewcontrollers. Group them into storyboards as you see fit. That way if one storyboard gets conflicted, it will easier to reset it and then manually adjust it to the latest state. It is also less likely to get merge conflicts in the first place because it's unlikely that two coders will work on the same storyboard file. Usually working on the same file is fine, when editing different lines but storyboards are different. As soon as you open them you get all sorts of view misplaced stuff and other things edited into the xml automatically. So if you open one and didn't actually change anything, reset the changes and don't commit it.
I'm pretty green, but I'm trying to modify a simple program to fit my own needs. You may remember the "BirdWatching" app from "Your Second iOS App: Storyboards" in the iOS Developer's Library.
Anyway, I've refactored most of the names, etc., successfully (it still worked), but then I tried to get rid of a file that kept appearing, even though its name had been expunged (or so I thought) through refactoring. Shows up in the Assistant Editor, right next to the file to which it was refactored.
Now I've got a mess. I tried to move the entire project into it's own folder, but now the compliler won't recognize the info-plist file (says it doesn't exist, and two other files are showing up in red, depending on their position in the navigator. However, it's the WMDG-info.plist that the complier complains about. Specifically, it appears to be following the old path to the file, even after it's been moved and re-added.
I've tried quitting and restarting xCode, re-adding the files, etc. I've searched under every keyword I can think of, but can't find a solution.
Please help!
Thanks!
--Tim
Background: git -- or any other SCM -- can "successfully" merge Storyboards, xib's, and pbxproj files as at their core they are just xml. Sometimes there are conflicts which can be resolved by the usual conflict resolution strategies. But xib's and Storyboards are serialized formats of some pretty complex data structures, so the fun begins.
Just as with other source code, a successful merge doesn't guarantee all the merged changes work correctly together. With the files in question, git can successfully merge but Xcode sometimes displays a "Could not read archive" error when you try to open it - i.e., the merge corrupted the xib.
I've seen suggestions about having git ignore .xibs (not practical), or in .gitattributes disable diff by setting
*.xib -crlf -diff
Technically, that fixes the merge conflict/corrupted xib problem - but now somebody's changes are lost?
Similarly, the best recommendation I've seen for the project file is merge=union in .gitattributes:
*.pbxproj merge=union
Question: I've searched quite a bit and there doesn't seem to be a good solution. Can people with experience tell me what happens in a few use cases?
In the project I rename a file from x to y, and delete fileA. Meanwhile, another programmer committed changes to add fileC and delete fileD. What is the result of merge? I'm sure the actual file system changes will be correct, but in the Xcode navigator panel:
Will I see both x and Y?
Will fileA reappear because it's still in the other programmer's .pbxproj?
Will fileD still be there because it's still in my .pbxproj?
If git is ignoring .xib files - will I at least get a warning that a file was changed and is not being handled?
I wouldn't set any specific .gitattributes for project files or nibs these days.
Your problems merging concurrent changes to Xcode projects and xibs/storyboards exist in every team with more than one developer.
Xcode projects
A few tricks for dealing with Xcode project conflicts:
Take one side of the merge and manually apply the other changes after the merge. If you've deleted files they'll be in red, if you need to add them they'll be available to add.
When adding files to your targets they will go at the bottom of the 'Compile Sources' build phase. Avoid conflicts with other people by dragging them up this list to a random position.
Use .xcconfig files to configure your projects rather than the build settings section. Config files are trivial to merge.
My best advice if in doubt is to take one side of the merge, relax, and replay your additions.
XIBs and Storyboards
The format of XIBs (and therefor storyboards) has change significantly in recent months. I've found that additional objects are appended to the file's internal collections and merges can be done easily. If you're making changes to the same object, you may have to get in there manually.
This post from Itty Bitty Apps highlights the main changes:
The benefits of this new XIB XML format are many fold:
XIBs are much smaller (fewer lines of code).
A developer can easily read the XML and understand what it specifies in the user interface.
Merging XIBs is now much less likely to lead to broken XIBs. Before we would rarely even bother to try and merge a XIB or Storyboard.
I'm at a complete loss as to what I did to cause this:
For the second time since I started using XCode about a month ago (my first time seriously using it after taking one class several years ago) I try to run my project and the next thing I know I have errors because I have duplicate references. I looked at the project and it appeared that most of the files in my project had duplicated themselves, however I discovered that they are not duplicate files just duplicate references. This happened to me today when I tried to build on an actual iphone for the first time but it also happened to me a few weeks ago while using the simulator. Neither time do I recall doing anything unusual. I have built and tested the project probably 100+ times and normally all goes ok. I was able to fix it the first time but I think I have made it worse this time and am probably going to add the files back into a new project. My co-worker also mentioned this happening to him (he has about as much experience with xcode as I do). He told me he ended up with files nested in folders (groups?) nested in other folders about 20 deep.
My question is this: Does anyone know what I may have done to cause this. I would really like to avoid this problem in the future since it is proving to be quite a headache. Any advice would be greatly appreciated.
E.T.A. xcode version 4.6.2 (possibly an earlier version the first time it happened)
Try this instead:
Highlight all the duplicate files
Right click on one of the files and press "Delete"
When prompted for which delete option, click "Remove Reference"
Also you asked for "any advice".
If you aren't already using git source control in your Xcode projects, start now.
You can spot many mistakes like this earlier and fix them more easily using git.
When you add files as a copy, the Xcode project navigator shows added files with an A and modified files with an M.
If the file is inside a closed group folder, the folder shows an A.
If you add a reference without a copy the project navigator won't show an A but MyApp.xcodeproj will show M.
In Xcode you can discard a change before committing it.
In the case below, you would discard changes to all added or modified files.
Typically you review and commit changes frequently.
Using a gui tool such as SourceTree, you have a good chance of spotting an accidental change before you commit. For example, you can see changes to the project file.
If you accidentally commit an unintended change, you can go back later and reverse a commit.
By committing frequently, you have more control over which changes you undo and which ones you keep.
References:
http://www.raywenderlich.com/13771/how-to-use-git-source-control-with-xcode-in-ios-6
http://git-scm.com/doc (scroll down to see videos)
http://www.sourcetreeapp.com
http://gitimmersion.com
I had the same 20 deep nesting of my main folder of images. If its not a bug its very strange behaviour. I just backed it all up !! Then I opened the folder in finder, found the point at which it was starting to nest and deleted it.
I did a rebuild, but I don't think Xcode even noticed. It made no difference to the size of my app so Xcode was not putting unnecessary files in the binary.
This happened to me when I imported a file. Suddenly I had two nested directories containing what looked like copies of all my files. The compiler complained about duplicate classes.
I found a solution, but it's a ball-ache and a time sink.
1: Click on your project in the navigator to open up the project settings in the main view.
2: Open the 'Compile Sources' accordion entry.
(This allows you to see which files are being used in the compilation process.)
3: Find any duplicates in here and delete them.
(At this stage your project should compile again.)
4: In your navigator view, slow-double-click one of the files that's duplicated there. This should allow you to rename it. Change the name (not the extension) slightly.
5: You should notice that the copy becomes red. Select it and hit delete.
(This avoids the delete operation removing the file from the 'Compile Sources')
6: Rename the original file back to its original name again.
7: Repeat from 4 until done, or until bored.
8: Explain to your boss why a simple copy change took half a day.
This process can be optimised up by first renaming all duplicated files, then deleting the duplicates all at once. However this means that you can't test for successful compilation between steps, which allows you to narrow the culprit down to a single file. And takes even more time.
If compilation fails, ensure all the files you need are still in the 'Compile Sources' section, as this process can cause them to be lost from there. The compiler will normally give some reasonable errors about missing classes and variables, but a missing AppDelegate will produce a more confusing error.
Storyboards are rather a royal pain from a git workflow perspective when multiple people are collaborating on them. For example, the XML in the .storyboard file has its starting <document> tag's toolsVersion and systemVersion attributes altered by whatever configuration the most recent file manipulator happens to be running. Synchronizing everybody's Xcode versions precisely seems to help with toolsVersion, but systemVersion changes no matter what, depending on the specific Mac and/or OS X version the developer is running.
This is idiotic, but mostly harmless. What worries us, though, is that at other times some other changes are automatically made to the storyboard just by opening them after a git pull. That is to say, Alice makes changes to a storyboard, commits and pushes them to the repository. Bob then pulls Alice's changes and opens up the storyboard to make further changes. The moment he opens the storyboard, the file icon immediately changes to a modified-but-unsaved state, and a git status shows that any number of weird changes have occurred. All this without Bob having changed anything or saved the file himself.
The most common automated change we're seeing is the disappearance or reappearance of the entire <classes> tag hierachy near the end of a storyboard file. We haven't figured out what is causing this. We may have several localized versions of a storyboard in various .lproj directories, and when opening them inside Interface Builder, the class hierarchy may spontaneously be removed from some and added into others, or left alone in some. This causes a lot of noise in git diff, but it doesn't actually break any functionality. We will often selectively add the actual changes we made into git's index, commit those, and then just discard the spontaneous, nonsensical <classes> changes. This is to keep commits small and nice, as they should be. Eventually, though, it just becomes too much to bother with since Xcode keeps re-doing the changes, and someone just ragecommits them along with some other stuff... which is fine until someone else's Xcode decides to want to change them back for no apparent reason. (Our commit history has a lot of swearing over this.)
Is anyone else seeing this behaviour? Is this an Xcode bug or a configuration issue on one or more of our developer Macs? We've seen some similar behaviour when collaborating with XIB files, but storyboards seem more susceptible to this.
This is not a bug, this is a consequence of how Xcode processes storyboard files.
I am writing a diff and merge program for storyboard files (GitHub link) and I have spent hours analyzing the storyboard files logic and how Xcode processes it. This is what I discovered:
Why do weird changes occur in storyboard files?
Xcode uses the NSXML API to parse storyboard files into some NSSet-based logical tree structure. When Xcode needs to write changes it creates an NSXMLDocument based on the logical tree structure, clears the storyboard file and calls XMLDataWithOptions: to fill the file again. Because sets do not preserve the order of their elements, even the slightest modification could change the whole storyboard XML file.
Why does the class tag disappear or reappear randomly?
The <class> section is nothing more than an internal Xcode cache. Xcode use it to cache information about classes. The cache changes often. Elements are added when class .h/.m files are opened and removed when Xcode suspects they are outdated (at least older Xcodes behave like this). When you save the storyboard, the current version of the cache is dumped, which is why the <class> section often changes or even disappears.
I have not reverse-engineered Xcode; I made these observations by experimenting with Xcode and storyboard files. Nevertheless, I am almost 100% sure it works this way.
Conclusions:
Cache section is unimportant; you can safely ignore any change in it.
Contrary to what you can find on all forums, merging storyboards files is not a complicated task. For example, let’s assume you changed MyController1 view controller in a storyboard document. Open the storyboard file, and find something like this
<viewController id=”ory-XY-OBM” sceneMemberID=”MyController1”>.
You can safely commit only changes in this section and ignore everything else. If you changed segues or constraints, also commit anything that has “ory-XY-OBM” inside. Simple!
This is a bug in XCode 4.5+, I hope it gets fixed, and yes its a PITA.
Here's the full bug at Apple
How to avoid Xcode gratuitous edits to storyboard files?
This issue can be mitigated somewhat by extremely judicious use of git add -p on any of Xcode's generated files, including storyboards, XIBs, Core Data models, and project files, all of which suffer from similar transient modifications that have no impact on the actual interface/model/project.
The most common junk changes I've seen on storyboards are the system version numbers (as you mention) and the constant addition and removal of the <classes> section, the omission of which I have never seen cause problems. For XIBs, it's the addition and removal of <reference key="NSWindow"/>, which isn't even a class in Cocoa Touch. Just wow.
Think of it like the sea: there is both a high and low tide. Let it wash over you.
Ahh. That's it.
You can ignore these modifications when staging your changes, reset the junk changes, and make a clean commit.
The single advantage I've seen with storyboards over XIBs from a technical standpoint is that Apple has not yet neutered FileMerge to refuse to merge conflicted storyboards. (FileMerge used to be able to merge XIBs, but newer versions broke that. Thxxxx guys 💜!!!)
Please file lots of bugs about all of these problems at http://bugreporter.apple.com/! And don't forget to create entries on OpenRadar.
Throwing on another answer here because this situation has improved greatly. The XML for the XIB file that represents the StoryBoard has been greatly simplified.
I have also recently bitten the bullet and started to use the interface in Xcode to Source Control. I have been on the command line for years and happy there, but the interface is nice and it lets you split commits, which is really important if you use a ticketing system that links to commits.
Anyway, I noticed today that there was a change on the storyboard and the built in diff showed me it was a single attribute in the document tag (systemVersion). So not a big deal.
I have read articles where people say SBs were outlawed on their teams because of merging issues. Total madness. They are so amazing, especially now that they have intelligent autolayout built in, you are really missing out if you are not using them.
It's helpful to know why this insanity is happening, but for those who believe in keeping their projects free of warnings and who just want a quick-and-dirty to get their projects back to a healthy state:
Don't commit anything until explicitly instructed.
Open Xcode and create a new storyboard (Command+N > iOS > User Interface > Storyboard). I'll assume you call it the default name of Storyboard.storyboard.
Open the storyboard that Xcode has violated. I'll assume this is Base.lproj/Main.storyboard.
Select and copy everything on the storyboard (Command+A then Command+C).
Open Storyboard.storyboard.
Copy and paste everything into Storyboard.storyboard.
Close Xcode.
Open a terminal and change directories to your repository.
Replace Main.storyboard with Storyboard.storyboard (mv Storyboard.storyboard Base.lproj/Main.storyboard).
git add Base.lproj/Main.storyboard; git commit -m "Fix Xcode's insanity."
Disregard the changes to project.pbxproj via git checkout -- project.pbxproj. If you git diff the file, you'll see that it has just added information about our temporary storyboard (which no longer exists).
Open Xcode back up and see that the warnings has disappeared.
Breathe.
Working on same storyboard is not a problem. But working on same viewcontroller which creates conflicts on pull/merge is frightening. we can not really avoid that working in same viewcontroller for a large team.
Good thing is, most of the time we can fixed the same viewcontroller conflicts if we understand the xml structure. I never failed to merge these while working in team. Suppose you are working with a viewcontroller. Your view is blank currently. Please ,have a look at the viewcontroller's xml structure from source code option.
Storyboard is xml bounded by document type tag. Everything in the storyboard contains in scene sceneID= tag. scene tag holds every viewcontrollers. Thats the basic.
Now we added a UILabel and a UIButton on the view. Also set the autolayout of the elements. Now it's looks like :
Adding a level/button to viewcontroller added some new code inside the subview tag of the view. Same thing will go for further element addition or any UI changes. Carefully check the tag structure which is really important to fix any conflicts.
Now we add another viewcontroller in the storyboard name Homeviewcontroller. Adding a new viewcontroller means it adds a new scene under scenes tag. Look at this:
At this point, we will change the structure randomly and observe the issues/warnings. We change first viewcontroller label end tag and save the file. Now run it and look at the warning. Error says end tag is not correct which created from line 23. In line 23 , we see a label constrains is set with no end tag. That's the problem. Now we put the end tag and build the project. After setting end tag, we can view the storyboard successfully.
When face any warning of conflicts , please compare with your previous source and changes source. We remove the old/redundant code , keep the new code with proper tag start-end and get things fixed.
[N.B , i will update the answer with some more test cases when get times]