Categories
ChatGPT iOS Development

Using ChatGPT for Swift iOS development

Lately, I also jumped onto the ChatGPT train and wanted to give it a try for the use in Swift development for the iOS platform. Here are my experiences so far using it for around 1 or two months now.

How to get access without sharing your (real) phone number

It’s still free and pretty much unlimited as far as I know. I never ran into any server overload issues etc. You can just go to chat.openai.com register and start using it. The interface is pretty self-explanatory and straightforward.

What kept me back the most all this time was not my disinterest but that you are forced to give them a real phone number. Which is still the case and it really sucks. Nobody knows what it’s used for or who has access. It’s a little shady.

Don’t spend any time on searching and trying these free online SMS receiver services. Non of them is working for registering for ChatGPT. I tried a lot of these for some hours. Just don’t do it.

A better time investment when you do not want to share your real number is to just get a prepaid SIM (here in Germany you can get them for around 5€) and put them in any cellphone.

My use case in short

I finally decided to order that burner SIM card and try it out, because I had a pretty clear use case in my mind. What I wanted to do was generating default plant care data for a gardening app I am working on as a side project.

My idea was to give the user based on any plant’s genus some plant care data that works out for most species of that genus. If you are asking yourself what is “genus” or “species”: In biology, this is used to classify any organism. E.g. for a well known typ of plant: “Monstera” is the genus and “deliciosa” is the species. There are other super- and subclasses in taxonomy but they do not matter for now.

If you are more interested on that topic, here is a short PDF by the University of Nebraska-Lincoln: https://alec.unl.edu/documents/cde/2017/natural-resources/classification-and-naming-of-plants.pdf

OK, so my plan was:

  1. Get a list of most common indoor houseplants
  2. Somehow populate a dictionary or something I can copy out of the chat window that contains all the data I need.

I will continue explaining how I tackled this plan in more detail in a minute.

It’s all about the prompts

Obviously, whether or not ChatGPT returns something useful is based on your prompts. It’s the only way you can interact with it. This means, similar to how your Google results are determined by how skillful you are in using Google, you can also help or mislead ChatGPT with your questions (That’s already a small spoiler regarding whether or not I am convinced that ChatGPT alone will replace Swift iOS development or my job as a developer).

Yes, handling ChatGPT might be way easier for a lot of people compared to doing proper Google searches. This is because it accepts natural language. Google instead works best with good keywords and you still have to scroll through the results.

What is fundamentally different, is that ChatGPT often gives you one answer that might or might not work. Google often leads you to some StackOverflow thread instead where you get some more context via comments. Often enough the code ChatGPT offers you does not even compile. From what I experienced, it’s often not syntactically incorrect but types might be handled wrong, deprecated APIs are used etc.

Designing your prompts

Similar to how you would tackle any problem in software development, you also need to do that when talking to ChatGPT. Think of ChatGPT like an iOS colleague with whom you are doing kind of pair programming, willingly helping your Swift development in whatever way.

This means we need to give ChatGPT some more constraints to return something useful. E.g. just start with defining a data structure you would like to use.

I need a struct representing plant care data with three properties: plantGenus, watering, humidity and lightRequirements 

It will result in something that works out but is probably not what you really wanted:

struct PlantCareData {
    let plantGenus: String
    let watering: String
    let humidity: String
    let lightRequirements: String
    
    init(plantGenus: String, watering: String, humidity: String, lightRequirements: String) {
        self.plantGenus = plantGenus
        self.watering = watering
        self.humidity = humidity
        self.lightRequirements = lightRequirements
    }
}Code language: Swift (swift)

As you can see, all of the properties are Strings which is not really great if you think about doing some analytics on these values, creating a UI with icons for each level, etc. What we want is something like an enum maybe with different levels.

With the following prompt I was already hooked. I gave it this quite rudimentary prompt:

Please change the type of watering to an enum that represents the amount of dryness needed before watering, e.g. β€œlet fully dry”. Use four cases that seem to make sense

As you can see, I only gave it only an example of one case but it came up with something pretty useful:

struct PlantCareData {
    let plantGenus: String
    let watering: WateringDryness
    let humidity: String
    let lightRequirements: String
    
    init(plantGenus: String, watering: WateringDryness, humidity: String, lightRequirements: String) {
        self.plantGenus = plantGenus
        self.watering = watering
        self.humidity = humidity
        self.lightRequirements = lightRequirements
    }
}

enum WateringDryness: String {
    case letFullyDry = "Let fully dry"
    case letPartiallyDry = "Let partially dry"
    case letMoist = "Keep moist"
    case waterFrequently = "Water frequently"
}Code language: Swift (swift)

This is pretty awesome already I’d say. Typing the prompts here was way easier than thinking about the cases let alone typing everything of this. However, we are not finished yet.

Of course the same works for the other properties as well:

Do something similar with humidity. Use an enum for that property that has six different cases with most common humidities for houseplants.
// Left out all the previous code here

enum HumidityLevel: String {
    case low = "Low humidity"
    case moderateLow = "Moderate low humidity"
    case moderate = "Moderate humidity"
    case moderateHigh = "Moderate high humidity"
    case high = "High humidity"
    case veryHigh = "Very high humidity"
}Code language: Swift (swift)

What I really liked was how you can fine-tune the results. I wanted to have some less ambiguous data, i.e. I asked it to add some numbers:

Please add some percentages of humidity to these levels for more details what is meant by the descriptions.

And the result looks pretty convincing again!

enum HumidityLevel: String {
    case low = "Low humidity (less than 30%)"
    case moderateLow = "Moderate low humidity (30-40%)"
    case moderate = "Moderate humidity (40-50%)"
    case moderateHigh = "Moderate high humidity (50-60%)"
    case high = "High humidity (60-70%)"
    case veryHigh = "Very high humidity (more than 70%)"
}Code language: JavaScript (javascript)

Lastly, I wanted to get some more usefule type for the lightRequirements property:

Please help me with the lightRequirements as well. This enum should have four different cases with different levels of light that do make sense for houseplants.
enum LightIntensity: String {
    case lowLight = "Low light"
    case mediumLight = "Medium light"
    case brightIndirectLight = "Bright indirect light"
    case directSunlight = "Direct sunlight"
}Code language: Swift (swift)

Again, pretty convincing πŸ™‚ We learned so far: ChatGPT can create nice Swift enums. Don’t get me wrong, I do not want to undervalue this, it’s pretty useful already!

But now lets get serious!

Now, please create some data based on that struct for me.
Please create an array of type PlantCareData based on the 10 most common houseplants.

Let’s highlight again the simplicity of this: You can ask it to reference anything you created together before (“based on that struct”, “array of type PlantCareData”) and enrich it with some very blurry requests (“the 10 most common houseplants”).

It does not ask for any further clarification, it’s first idea already looks awesome! There are still errors but let me show you the result first:

// Define the PlantCareData objects
let plant1 = PlantCareData(plantGenus: "Monstera deliciosa",
                           watering: .letSoilDry,
                           humidity: .moderate,
                           lightRequirements: .mediumLight)

let plant2 = PlantCareData(plantGenus: "Pothos",
                           watering: .keepMoist,
                           humidity: .moderateLow,
                           lightRequirements: .lowLight)

let plant3 = PlantCareData(plantGenus: "Snake plant",
                           watering: .letSoilDry,
                           humidity: .low,
                           lightRequirements: .lowLight)

let plant4 = PlantCareData(plantGenus: "ZZ plant",
                           watering: .letSoilDry,
                           humidity: .low,
                           lightRequirements: .lowLight)

let plant5 = PlantCareData(plantGenus: "Spider plant",
                           watering: .keepMoist,
                           humidity: .moderate,
                           lightRequirements: .mediumLight)

let plant6 = PlantCareData(plantGenus: "Peace lily",
                           watering: .keepMoist,
                           humidity: .high,
                           lightRequirements: .mediumLight)

let plant7 = PlantCareData(plantGenus: "Dracaena",
                           watering: .keepMoist,
                           humidity: .moderate,
                           lightRequirements: .mediumLight)

let plant8 = PlantCareData(plantGenus: "Aloe vera",
                           watering: .letSoilDry,
                           humidity: .low,
                           lightRequirements: .brightIndirectLight)

let plant9 = PlantCareData(plantGenus: "Rubber plant",
                           watering: .letSoilDry,
                           humidity: .moderate,
                           lightRequirements: .mediumLight)

let plant10 = PlantCareData(plantGenus: "Fiddle leaf fig",
                            watering: .letSoilDry,
                            humidity: .moderate,
                            lightRequirements: .brightIndirectLight)

// Create an array of PlantCareData objects
let houseplants: [PlantCareData] = [plant1, plant2, plant3, plant4, plant5, plant6, plant7, plant8, plant9, plant10]
Code language: Swift (swift)

This is awesome right!? Let’s recap what happened:

  1. It found ten most common houseplants
  2. It found data about watering, humidity and light requirements for each of these plants
  3. It somehow mapped this data to the enums you created earlier!

The result above looks convincing again, but if you are trying to copy everything into one Swift Playground it won’t compile. Why? If you compare the enums I posted here, you will see that it renamed some cases during the process (for whatever reason). However, this might also have something to do with my prompts. Maybe if you always add something like “make sure that this and this from before is included” it might work better.

After going back and forth, telling ChatGPT what’s wrong, which case is missing, etc. you will get something that works. However, at this point I often realized that it might have been easier to just fix these bugs by yourself.

What I learned so far

The talking about ChatGPT replacing software developers is BS in my opinion. You still need someone to guide it and this someone needs enough knowledge to know whether the responses make sense or not. Copying stuff straight from ChatGPT that does exactly what you want works for really easy things (e.g. creating SQL statements where you tell it the exact column names). For other cases (at least to me) it’s really great for returning a first idea (with good explanations) that you can manually improve.

In addition to that, it’s great if you are unsure about how to tackle something, e.g. “What is the most efficient way of accessing/updating/whatever an array objects in Swift having these kind of properties”. It will give you a nice explanation with weighing in pros and cons of different approaches. If you don’t quite understand something, you can ask it for clarification.

Conclusion

In the context of Swift iOS development at least to me ChatGPT is really great for learning e.g. how to properly access this or that? What is the advantage of doing it like this? Is there a better way of doing that? Questions like this lead to great results for me so far.

For code generation it’s fun to use and it’s awesome to see what it can generate. However, often enough there are tons of bugs, when asking it for fixes, it mangles up other stuff, etc. For me at this point it’s best for creating early drafts that I can manually improve later on.

Let’s see what comes with later updates, so far it looks really convincinv

Leave a Reply

Your email address will not be published. Required fields are marked *