It's worth noting that the iOS7 SDK introduced the ability to do encode and decode Base64 data natively. Have a look at the NSData Class Reference
–
AbizernNov 24 '13 at 12:06

4

Perhaps the accepted answer should be changed to one of the answers that points out that not only does iOS 7 do this natively, but Apple has exposed the previously private methods to do it in iOS versions going back to 4.0. The historically top-rated answers (including the accepted answer) really are not advisable anymore. They were great back in the day, but nowadays, it's probably a poor choice to use a third-party base-64 library. I posted a more contemporary answer, as have a few others.
–
RobMar 15 '14 at 2:14

Watch out! There's a nasty bug in the NSData category posted there. The line: realloc(bytes, length); is wrong; you need to take into account the return value of realloc.
–
Nick HutchinsonJun 17 '11 at 23:57

A really, really fast implementation which was ported (and modified/improved) from the PHP Core library into native Objective-C code is available in the QSStrings Class from the QSUtilities Library. I did a quick benchmark: a 5.3MB image (JPEG) file took < 50ms to encode, and about 140ms to decode.

The code for the entire library (including the Base64 Methods) are available on GitHub.

Or alternatively, if you want the code to just the Base64 methods themselves, I've posted it here:

Finally a correct and efficient implementation. Thanks. Some of the other code around here scares me.
–
Mike WellerNov 8 '11 at 7:53

3

The memory allocated as strResult in the encoder seems to be leaked; it just needs a free() at the end (before returning but after NSString stringWithCString)
–
JosephHNov 25 '11 at 14:20

2

In your encodeBase64WithData: method, doesn't the first parameter in the call to calloc() need to be incremented by 1 to account for the null terminator ('\0') you add at the end?
–
erikpriceJan 30 '12 at 23:00

1

The fact that apple doesn't provide this makes God want to murder kittens... a lot of them...
–
dsingletonMay 18 '12 at 16:50

2

I've been using this for a while and it seemed to work great until I started getting some memory corruption related errors and using guard malloc I narrowed it down to this line: *objPointer = '\0'; so beware if you use this in your own apps.
–
MattiaJul 20 '12 at 18:55

Historically we would have directed you to one of the many third-party base 64 libraries (as discussed in the other answers) for converting from binary data to base 64 string (and back), but iOS 7 now has native base 64 encoding (and exposes the previously private iOS 4 methods, in case you need to support earlier versions of iOS).

Thus to convert NSData to NSString base 64 representation you can use base64EncodedStringWithOptions. If you have to support iOS versions prior to 7.0 as well, you can do:

Obviously, if you don't need backward compatibility with iOS versions prior to 7.0, it's even easier, just use base64EncodedStringWithOptions or initWithBase64EncodedString, respectively, and don't bother with the run-time check for earlier iOS versions. In fact, if you use the above code when your minimum target is iOS 7 or greater, you'll actually get a compiler warning about the deprecated methods. So, in iOS 7 and greater, you would simply convert to base 64 string with:

Thanks about that Rob. Could you please briefly elaborate on what you wrote, "...and exposes the previously private iOS 4 methods"?
–
IreneJan 28 '14 at 8:21

2

@Irene The base64Encoding method has actually been there since iOS 4 (now deprecated in iOS 7.0, replaced by base64EncodedStringWithOptions), but it was a private method (i.e. a method that Apple may have used internally, but never released it to the public). In the past, because it wasn't included in the .h header files, you would have received a compiler warning if you tried to use it (even though it would have worked). Apple has now decided to make that previously private method public, giving us more backward compatibility in our use of native base 64 methods.
–
RobJan 28 '14 at 13:35

Perfect, thank you very much for the explanation
–
IreneJan 28 '14 at 14:20

2

It's a shame this answer is buried beneath all those custom implementations. It's a weakness of SO, where a more appropriate solution may have come about long after the original question was asked, that solution now has to compete with what was previously accepted.
–
jakevMar 15 '14 at 1:22

iOS includes built in support for base64 encoding and decoding. If you look at resolv.h you should see the two functions b64_ntop and b64_pton . The Square SocketRocket library provides a reasonable example of how to use these functions from objective-c.

These functions are pretty well tested and reliable - unlike many of the implementations you may find in random internet postings.
Don't forget to link against libresolv.dylib.

Since this seems to be the number one google hit on base64 encoding and iphone, I felt like sharing my experience with the code snippet above.

It works, but it is extremely slow. A benchmark on a random image (0.4 mb) took 37 seconds on native iphone. The main reason is probably all the OOP magic - single char NSStrings etc, which are only autoreleased after the encoding is done.

Another suggestion posted here (ab)uses the openssl library, which feels like overkill as well.

The code below takes 70 ms - that's a 500 times speedup. This only does base64 encoding (decoding will follow as soon as I encounter it)

I left out the line-cutting since I didn't need it, but it's trivial to add.

For those who are interested in optimizing: the goal is to minimize what happens in the main loop. Therefore all logic to deal with the last 3 bytes is treated outside the loop.

Also, try to work on data in-place, without additional copying to/from buffers. And reduce any arithmetic to the bare minimum.

Observe that the bits that are put together to look up an entry in the table, would not overlap when they were to be orred together without shifting. A major improvement could therefore be to use 4 separate 256 byte lookup tables and eliminate the shifts, like this:

Hmm. I couldn't get this to work. I observe a different base64 encoding than my expected value. Have you tested this with the examples in RFC 4648? tools.ietf.org/html/rfc4648
–
Alex ReynoldsMay 7 '10 at 19:21

3

Struggling to see what base64EncodingTable1, base64EncodingTable2, base64EncodingTable3 and base64EncodingTable4 are referencing?
–
Jamie ChapmanJul 31 '10 at 13:34

Very helpful, but it can read beyond the end of the input buffer. When (left==2), raw[inp+2] will be one byte beyond the end of tmpbuf. I think the line should be: if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2)];
–
John LembergerNov 15 '10 at 17:16

According to the documentation: "Although this method was only introduced publicly for iOS 7, it has existed since iOS 4; you can use it if your application needs to target an operating system prior to iOS 7". This existed but was private prior to 7. You should be careful using it if your application is not linked against the 7 SDK.
–
quellishOct 24 '13 at 7:15

We can do that based on the iOS version on which the app is running using "[[UIDevice currentDevice] systemVersion].floatValue".
–
NagarajOct 24 '13 at 12:20

2

1. That would not tell you what SDK you linked against, that is a runtime check. 2. That is directly counter to Apple's guidance. You should be checking for the availability of a feature, not the system version.
–
quellishOct 24 '13 at 19:28

you already have an account here, as your previous answer is actually a different account. Also, this should be either an edit to that or a comment.
–
Alastair PittsJul 6 '10 at 0:16

@alastair, you seem to get an "account" every time you post an answer without registering, after cleaning cookies. I wasn't able to connect to my first "account" (even with the same email and ip address) so I just put it there as a new answer, sorry for that. -- just registered!
–
mvdsJul 8 '10 at 21:07

3

Any chance you could edit this answer into your previous one so there's a definitive correct version? Thanks!
–
JosephHOct 20 '11 at 12:28

iOS has had built-in Base64 encoding and decoding methods (without using libresolv) since iOS 4. However, it was only declared in the iOS 7 SDK. Apple documentation states that you can use it when targeting iOS 4 and above.