You absolutely could write SQL queries and store whatever data you need in a SQLite database or just write raw data to a file. In fact you are free to do so right now in an iOS app. Why then might we want a different abstraction?
Immediately you're going to notice that your application is working with objects and you need to translate them into some form you can write to your data store. You might just write a bunch of raw bytes from memory to disk but that will be very hard to reconstruct back into an object of the appropriate type and as soon as you change an object's structure your data will be even more difficult to recover. Instead you'll probably decide to serialize the object into some more reasonable form. That works well if you just want to write to a file but then it is hard to selectively reconstruct objects. No problem, you store data in sqlite in a form you can query on and now you can quickly search for and load specific objects. Of course its inconvenient to have every class in your app handle a bunch of database reads and writes, you probably want some service which can automate mapping classes to tables and objects to rows in those tables. Now you've build your own object-relational mapping library.
Mapping objects to rows in tables is a good start but some of your objects contain other child objects so you end up needing to save and load entire graphs of objects at a time. That's ok with a little work you can handle that too.
Oh and it would be nice if you could double check that your data is valid before you actually save it so you might add some rules to prevent saving invalid objects to the database.
Your ORM library works great but as you keep working on the app you discover that you need to change some of your objects. That means you need to change how they are represented in the database too. Now you need to define some process for migrating an old database schema to a new one.
As your app grows it becomes infeasible to store all of the results of some of your queries in memory. You solve that with a clever scheme for just loading a few objects at a time as they are needed.
Then you discover that users sometimes want to undo their changes. You could store each change as a row in a table but after doing that a couple of times you realize that your data storage service could automatically keep track of changes for you.
Now you have a pretty powerful tool for managing persisted objects in your application. Its so handy it would be nice if you could use it in other situations too, like for objects you just want to keep in memory and not write to a database. Of course then it would be even better if you could choose to move some of those objects over into the database later.
You have now reinvented most of CoreData. An attempt to build a fairly general purpose tool for persisting objects and managing common operations around their persistence. You don't use it for everything but it's awfully handy to pull into your apps as soon as they have some non-trivial requirements around how they manage data.