Adding iCloud to an app

Syncing files via iCloud in an app is easy and can be done with a few steps. It syncs a certain directory between devices so that you have the same files available on every device of the same user: Turn iCloud support on in XCode for your project. You just have to turn the switch … Continue reading “Adding iCloud to an app”

Syncing files via iCloud in an app is easy and can be done with a few steps. It syncs a certain directory between devices so that you have the same files available on every device of the same user:

  1. Turn iCloud support on in XCode for your project. You just have to turn the switch on and turn iCloud Documents on in the next screen that appears.. Afterward the app can use the iCloud and has a directory that is automatically synced between devices.
    Screenshot_06_09_15_01_24
  2. To move a local file into the iCloud you just have to move it from a local directory into the iCloud directory using a special command. The sync is performed automatically afterward:
    NSError *error = nil;
    NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    NSURL *targetDirectory = [ubiq URLByAppendingPathComponent:@"Documents"];
    [[NSFileManager defaultManager] setUbiquitous:TRUE itemAtURL:sourceFileURL destinationURL:[targetDirectory URLByAppendingPathComponent:filename] error:&error];
  3. When reading files from the iCloud you have to take into account that they might not have been downloaded yet. So to read a file from the iCloud you have to trigger a download and then wait for the file:
    [[NSFileManager defaultManager] startDownloadingUbiquitousItemAtURL:fileURL error:&error];
    NSFileCoordinator *coordinator = [[[NSFileCoordinator alloc] initWithFilePresenter:nil] autorelease];
    [coordinator coordinateReadingItemAtURL:fileURL options:0 error:&error byAccessor:^(NSURL *newURL) {
       // Here you can access the downloaded file.
    }];
    
    

These are the basic steps to use iCloud with files (there are also other options, this here is just a simple way to sync files). However there are some more useful functions:

Listing files

While OS X automatically downloads all iCloud files, iOS doesn’t. So it can happen that you won’t find all available files in the iCloud directory. Instead you have to use a special function to get a list of available files. It is again asynchronous:

self.queryiCloudMetaData = [[[NSMetadataQuery alloc] init] autorelease];
queryiCloudMetaData.searchScopes = @[NSMetadataQueryUbiquitousDocumentsScope];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshiCloudFiles:) name:NSMetadataQueryDidFinishGatheringNotification object:self.queryiCloudMetaData];
[queryiCloudMetaData startQuery];

- (void)refreshiCloudFiles:(NSNotification *)notification {
    [queryiCloudMetaData stopQuery];

    for(NSMetadataItem *item in [queryiCloudMetaData results]) {
       // process the iCloud file item
    }

    self.queryiCloudMetaData = nil;
}

Deleting a file

To delete a file you have to use an NSFileCoordinator to access the file and then an NSFileManager function to delete it:

NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateWritingItemAtURL:fileURL options:NSFileCoordinatorWritingForDeleting
 error:nil byAccessor:^(NSURL* writingURL) {
 NSFileManager* fileManager = [[NSFileManager alloc] init];
 [fileManager removeItemAtURL:writingURL error:nil];
}];

Key-Value table

This is an even easier method to sync via iCloud. To save a value into the synced key value table just write

[[NSUbiquitousKeyValueStore defaultStore] setString:@"test" forKey:@"testkey"];

And to read a value write

[[NSUbiquitousKeyValueStore defaultStore] objectForKey:@"testkey"];

The key-value table is automatically synced between all devices that are connected to the iCloud account. To be informed when something changes register an observer:

- (void)registeriCloudKeyValue {
    // register to observe notifications from the store
    [[NSNotificationCenter defaultCenter]
            addObserver: self
               selector: @selector(storeDidChange:)
                   name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification
                 object: [NSUbiquitousKeyValueStore defaultStore]];

    // get changes that might have happened while this
    // instance of your app wasn't running
    [[NSUbiquitousKeyValueStore defaultStore] synchronize];
}
- (void)storeDidChange:(NSNotification *)notification {
    ...

Then you can access the changed keys using

NSArray *changedKeys = userInfo[NSUbiquitousKeyValueStoreChangedKeysKey];

iOS Simulator

To test these iCloud functions with the iOS Simulator you have to sign in to your iCloud account in the “Settings” app of the iOS Simulator. I have tested it with iOS 8.4 and it mostly works, but there are some problems:

  • Changes to Key-Value tables seem to be only sent to the iCloud but they are not received.

 

Logging incoming connections (TCP, Linux)

On a server that I am running MRTG showed me some spikes in incoming connections. It seems that about 800 incoming tcp connections were made within a few minutes. Nagios reported that there were so many connections that no further connections could be created. To examine the problem I wanted to log all incoming TCP … Continue reading “Logging incoming connections (TCP, Linux)”

On a server that I am running MRTG showed me some spikes in incoming connections. It seems that about 800 incoming tcp connections were made within a few minutes. Nagios reported that there were so many connections that no further connections could be created. To examine the problem I wanted to log all incoming TCP connections. This can be done with a single command:

iptables -I INPUT -p tcp --syn -j LOG --log-prefix='[tcpconnections] '

It temporarily adds a rule to the firewall’s INPUT chain to write all incoming TCP packets that have the SYN flag set, i.e. that try to initiate a connection, into the system’s log with the prefix “[tcpconnections] “. Afterward you can see the connections e.g. in /var/log/syslog.

However now the syslog is quickly filled with entries if your server has a lot of TCP traffic. To separate these entries and write them into a different log, add a file “tcpconnections.conf” to “/etc/rsyslog.d“:

:msg,contains,"[tcpconnections] " /var/log/tcpconnections.log
& ~

The first line copies the matching entries into the file /var/log/tcpconnections.log. The second line discards the same entries so that they are not additionally copied into the main syslog. The ampersand means that another action should be applied to the filter in the previous line. A good overview of these parameters can be found in the RedHat documentation here:

Basic configuration of rsyslog

To activate the changes, restart rsyslog:

/etc/init.d/rsyslog restart

Now all connections are logged to tcpconnections.log but the file can get large. So it should be rotated. To do this create a file “tcpconnections” in /etc/logrotate.d and write this into it:

/var/log/tcpconnections.log {
	daily
	rotate 12
	compress
        missingok
}

It will create a new log each day and keep the last 12 logs.