Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a PBXGroup #43

Closed
Daltron opened this issue Aug 17, 2017 · 17 comments
Closed

Creating a PBXGroup #43

Daltron opened this issue Aug 17, 2017 · 17 comments

Comments

@Daltron
Copy link

Daltron commented Aug 17, 2017

Is it possible to create a new PBXGroup and append it to the Xcode project?

I've tried this:

let project = try! XcodeProj(path: "MyProject.xcodeproj")
let pbxproj = project.pbxproj
let group = PBXGroup(reference: "CustomPBXGroup", children: [], sourceTree: sourceTree)
pbxproj.objects.groups.append(group)

but groups is read only property.

Is there a way to do this?

@filletofish
Copy link

filletofish commented Aug 17, 2017

@Daltron you need to change pbxprj.objects:

pbxproj.objects.append(.pbxGroup(newGroup))

@Daltron
Copy link
Author

Daltron commented Aug 20, 2017

@filletofish Thanks for replying. That adds it to the objects group but it doesn't show up in the actual xcodeproj when I write it back to the disk.

Here is how I am creating my group:

let project = try! XcodeProj(path: "testing.xcodeproj")
var pbxproj = project.pbxproj
var group = PBXGroup(reference: pbxproj.generateUUID(for: PBXGroup.self), // This doesn't seem right?
                     children: [],
                     sourceTree: pbxproj.objects.groups[2].sourceTree)
group.name = "CustomPBXGroup"

pbxproj.objects.append(.pbxGroup(group))
try! project.write(path: "testing.xcodeproj", override: true)

Am I doing something wrong here?

@filletofish
Copy link

@Daltron I have never tried it so. @pepibumur should now :)

@pepicrft
Copy link
Contributor

pepicrft commented Aug 21, 2017

Hey @Daltron
Can you try this?

let project = try! XcodeProj(path: "testing.xcodeproj")
var group = PBXGroup(reference: pbxproj.generateUUID(for: PBXGroup.self), // This doesn't seem right?
                     children: [],
                     sourceTree: pbxproj.objects.groups[2].sourceTree)
group.name = "CustomPBXGroup"
project.pbxproj.objects.append(.pbxGroup(group))
try! project.write(path: "testing.xcodeproj", override: true)

Notice that I don't create a new variable pbxproj from project.pbxproj. Since models are not classes, when you assign the value to a new variable, you are creating a copy of the value. When you add a new element, you add it to the copy, and not the value contained in the project.

Could you try and let me know if that works?

@yonaskolb
Copy link
Collaborator

Yeah, there's a rational for changing at least some of the top level structs to classes, to make things easier to update

@Daltron
Copy link
Author

Daltron commented Aug 21, 2017

@pepibumur That seems to add it to my xcodeproj when I look at the raw text, but what if I am wanting to add that group to a group that already exists in my xcodeproj?

I've tried

project.pbxproj.objects.groups[2].children.append(group.reference)

but since groups is a read only property, this won't work.

@pepicrft
Copy link
Contributor

pepicrft commented Aug 22, 2017

Good point @Daltron. What do you think about building an interface method like this one?

var myObject = project.pbxproj.objects.groups[2]
myObject.children.append(group.reference)
project.pbxproj.update(object: myObject)

Since objects include a reference we can find the object in the array and update it. What do you think? cc @yonaskolb

@yonaskolb
Copy link
Collaborator

I think all the different object types should be mutable arrays on the project, instead of having them be getters on the objects array. objects could still be a way to initialise the project.

This would also speed up the writing of a project a lot as those object type getters (for example object.fileReferences) get looked up a lot

@pepicrft
Copy link
Contributor

Good point, thinking about it, I think makes sense since we need to filter them later on when we export the project. Is there any advantage in having them as a single array?

@pepicrft pepicrft reopened this Aug 22, 2017
@yonaskolb
Copy link
Collaborator

The only advantage I can see is that the project properties used to be immutable so the only way to edit these was to use the initialiser which would have been crazy with a dozen different array. But now that things are mutable, they can be changed after the fact. The init param could be left as an optional though.

The object property could also still be used as a getter. I know its used for checking all the references for the reference generator, but this could be typed to a project element array.

Hope that makes sense :)

@yonaskolb
Copy link
Collaborator

Having said that, it makes it easier to add objects but doesn't really solve the problem of editing them. The fact is that Structs in an array are hard to edit as you have to pull them out, edit them and then update the array.
Your update function above would work (I'm guessing it would check against the type and reference to know which struct to update), but is still harder to use.

This would all be easier if they were classes. Would would be the biggest downside of having the project elements be classes?

@pepicrft
Copy link
Contributor

The more I think about it the more I think it'd make sense to move everything into classes. Thinking about the project as a tree of immutable elements I think it'd be much easier if those elements were just classes and you could modify the tree at any point that you want. We'd simplify the APIs a lot.

@pepicrft
Copy link
Contributor

What do you think @yonaskolb ?

@yonaskolb
Copy link
Collaborator

Agreed 👍

@pepicrft
Copy link
Contributor

I've created an issue to tackle the migration to classes. You can follow it up here #45

@yonaskolb
Copy link
Collaborator

@Daltron, now with release 0.1.0 you can add your group as follows:

let project = try! XcodeProj(path: "testing.xcodeproj")
var newGroup = PBXGroup(reference: pbxproj.generateUUID(for: PBXGroup.self), 
                        sourceTree: .group, 
                        name: "CustomPBXGroup")

// find your existing group
let existingGroup = project.pbxproj.groups.first { $0.name == "ExistingGroup" }!

// append the new group to the existing groups children
existingGroup.children.append(newGroup.reference)

//add the new group to the the list of groups
project.pbxproj.groups.append(group)

try! project.write(path: "testing.xcodeproj", override: true)

@Daltron
Copy link
Author

Daltron commented Aug 25, 2017

@yonaskolb Thanks for the prompt response! Looking forward to trying this out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants