iOS C/C++ Static Library Sizes

There is often alarm at the size of the Chilkat static libraries (.a) for iOS. This should not be of too much concern, because after building your app in Release mode, your app’s executable will NOT grow by the size of the static library. It will only grow by a very small fraction of the total size of the .a

There are some common misunderstandings about static libraries that should be cleared up.

  1. You do NOT include the static library (.a) in the package you submit to the app store.
  2. When building your program, Xcode only pulls in the library code that is directly or indirectly used.   (This is true for any C/C++ linker.)   If, for example, Chilkat added functionality for SNMP, Jabber, and Bitcoin, and if this new code caused growth in the .a by 100MB, then it would only cause an increase in your app’s size if your app actually uses the new code.
  3. You may be unaware of the vast number of already-existing system libs (.a) and the vast sizes if all of these were summed up.  Obviously, these are not included in their entirety in your app’s executable.  The same applies to the Chilkat static libs.
  4. You can always check to see how much your app’s executable actually grows in size after linking with Chilkat by examining the size of the executable after linking.
  5. The Chilkat universal lib is composed of both the simulator static libs (x86 + x86_64), and the device libs (arm64, armv7, armv7s).   Your application built for the App Store would not be including alternatives for the simulator.
  6. This Apple Technical Q&A discusses general techniques for reducing the size of an app:  https://developer.apple.com/library/ios/qa/qa1795/_index.html

iOS: Preparing your Apps for IPv6

Chilkat classes that communicate over TCP/TLS include a property named PreferIpv6. This should be set to YES/true to tell Chilkat to use IPv6 when possible. (If the underlying DNS resolution provides both IPv4 and IPv6 choices, then Chilkat will by default choose the IPv4 address. To tell Chilkat to choose the IPv6 choice, set the PreferIpv6 property equal to YES/true.)

Note: All Chilkat classes that communicate over TCP/TLS will include a PreferIpv6 property. This includes Http, MailMan, Imap, Ftp2, Socket, Ssh, SFtp, etc.

For more information, see Using IPv6 in Chilkat Apps for iOS

Chilkat v9.5.0 pre-release for iOS arm64 / x86_64 is Ready

A new build of Chilkat v9.5.0 supporting the arm64 and x86_64 iOS architectures is available:

http://www.chilkatsoft.com/preRelease/chilkat-9.5.0-ios.zip

The static libraries are provided differently than before. Chilkat provides static libs for each architecture slice: i386 (for the simulator), armv7, armv7s, arm64, and armv6 (for older versions of iOS). The libs are located in the directories as shown here:

lib/i386/libchilkatIos.a
lib/x86_64/libchilkatIos.a
lib/armv6/libchilkatIos.a
lib/armv7/libchilkatIos.a
lib/armv7s/libchilkatIos.a
lib/arm64/libchilkatIos.a

A bash shell script (makeUniversalLib.sh) is also provided to create a universal static library from the individual slices:

#!/bin/bash -ev
cd lib
libtool -static i386/libchilkatIos.a 
    x86_64/libchilkatIos.a 
    armv7s/libchilkatIos.a 
    armv7/libchilkatIos.a 
    arm64/libchilkatIos.a 
    armv6/libchilkatIos.a 
    -o libchilkatIos.a
cd ..

You may modify the makeUniversalLib.sh script so that it only includes the slices that are needed.
Your application should then link with the universal libchilkatIos.a that is created by this libtool command.

Helpful Hints for Monitoring Progress in iOS Applications

This is some advice from an iOS application developer using Chilkat FTP2.  It is about monitoring the progress of an FTP upload or download, but it’s a technique that can be considered for updating the UI for any long-running operation that provides percent-done event callbacks:
“It took me a while to avoid all the problems with updating the progress window in iOS 6, since all UIKit functions only work in the main task, but now everything is running perfectly (as perfect as software can ;-).
In short my solution:
The CkoFtp2Progress only handles the plain data and got updates from different parts of the program. And a installed NSTimer refreshes the UIWindow from the main task with the actual data in CkoFtp2Progress. Just in case someone asks you. I saw a lot of people having trouble with this point, while working on this solution.”

Auto-release Pools and Background Threads

Regarding Objective-C programming for MAC OS X and IOS:

(from https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html )

Cocoa always expects there to be an autorelease pool available. If a pool is not available, autoreleased objects do not get released and your application leaks memory. If you send an autorelease message when a pool is not available, Cocoa logs a suitable error message. The AppKit and UIKit frameworks automatically create a pool at the beginning of each event-loop iteration, such as a mouse down event or a tap, and drain it at the end. Therefore you typically do not have to create a pool, or even see the code that is used to create one. There are, however, three occasions when you might use your own autorelease pools:

If you are writing a program that is not based on a UI framework, such as a command-line tool.

If you write a loop that creates many temporary objects.

You may create an autorelease pool inside the loop to dispose of those objects before the next iteration. Using an autorelease pool in the loop helps to reduce the maximum memory footprint of the application.

If you spawn a secondary thread.

You must create your own autorelease pool as soon as the thread begins executing; otherwise, your application will leak objects. (See “Autorelease Pools and Threads” for details.)

IOS / Mac OS X Link Problems involving symbols such as __ZTVN10__cxxabiv121__vmi_class_type_infoE

If linking produces undefined symbols involving the following:

  • __ZTVN10__cxxabiv121__vmi_class_type_infoE
  • __Znwm
  • __ZdlPv
  • ___gxx_personality_sj0
  • ___cxa_begin_catch
  • __ZTVN10__cxxabiv120__si_class_type_infoE
  • ___cxa_end_catch
  • __ZdaPv
  • __ZTVN10__cxxabiv117__class_type_infoE
  • etc.

It means you’re NOT linking with the C++ runtime libs.  To link with the C++ runtime libs, include an empty source file having a file extension of “.cpp”.   For more information, see the IOS Objective-C linking notes

(IOS) Creating a Chilkat Universal Library

The Chilkat IOS library download provides separate static libs for the device and simulator. The universal lib is not included because (1) it is easy to create from the individual libs, and (2) it reduces the size of the download.

To create a single IOS Chilkat universal lib, run the following libtool command from the root of the Chilkat directory (where the Chilkat download files were extracted).

libtool -static -o libchilkatIos.a libDevice/libchilkatIos.a libSimulator/libchilkatIos.a

(IOS/IPhone) Setting Zip.TempDir to the Documents Directory

The Chilkat Zip methods for writing a .zip will first write the zip to a temp file in the directory specified by the Zip.TempDir property, and then if successful, moved/renamed to the actual output file. The default value for zip.TempDir is “.” (the current working directory) and this is often a directory where it is not possible to create files. On IOS, a good solution is to set the zip.Temp directory equal to the app’s Documents directory, as shown in the code snippet below.

* The reason a temp file is used is because quite often the call to WriteZip / WriteZipAndClose is overwriting an existing .zip archive. If Chilkat Zip were to write the output file directly, and the zipping failed mid-way, then the existing .zip would be lost. Using the temp file eliminates this situation. The existing .zip is overwritten only when the entire new .zip is written.

* Also, depending on the situation and the sizes of files involved, temp files may be used when unzipping. The location of the temp directory for both zipping and unzipping is controlled by the TempDir property.

- (NSString *)documentsDirectory {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
           NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}

...
...
CkoZip *zip = [[[CkoZip alloc] init] autorelease];
...
...
zip.TempDir = [documentsDirectory];

success = [zip WriteZipAndClose];
if (success != YES) {
    [strOutput appendString: zip.LastErrorText];
    [strOutput appendString: @"\n"];
    self.mainTextField.stringValue = strOutput;
    return;
}

...