Skip to content

iOS

The iOS SDK is designed to work in iOS mobile apps written in Objective-C or Swift.

Apps running the iOS SDK run an on device Textile peer (including a managed IPFS peer). The SDK provides you with a number of helpful APIs to manage sharing, contacts, file encryption & storage, and much more.

Below are some basic examples to get you started. If you are interested in a more thorough walk-through, check out the Tour of Textile's examples using Swift or Objective-C or jump to the full API documentation if you are ready.

Installation

The iOS is published as a pod on CocoaPod.org. The library is also published on GitHub.

CocoaPods

If you haven't already, you'll need to setup CocoaPods in your project. Next, add Textile to your project.

pod 'Textile'

This will install the latest version of the SDK into your app.

Carthage (experimental)

Carthage support is minimally tested today, but if you are a Carthage user and would like to try, we'd love a PR here to update this process.

github "textileio/ios-textile"

There you'll need two dependencies that are the Protobuf library from Google and the Textile Core iOS library available on our releases page. You can see how those are handled in our CocoaPods setup.

Getting Started

Initialize Textile

Objective-C

Then in your application delegate’s - application:didFinishLaunchingWithOptions: method, setup Textile as follows,

// Early on in the app lifecycle, usually in AppDelegate
// Initialize a new Textile wallet for the user.
NSError *error;
NSString *recoveryPhrase = [Textile initializeWithDebug:FALSE logToDisk:FALSE error:&error];
if (recoveryPhrase) {
  // Return phrase to the user for secure, out of app, storage
}
if (error) {
  NSLog(@"initialize error: %@", error.localizedDescription);
}
// Set the Textile delegate to any object that conforms to the TextileDelegate protocol
Textile.instance.delegate = delegate;

Swift

do {
  // recoveryPhrase should be optional here, fix coming asap
  let recoveryPhrase = try Textile.initialize(withDebug: false, logToDisk: false)
  // Return phrase to the user for secure, out of app, storage

  // Set the Textile delegate to self so we can make use of events such nodeStarted
  Textile.instance().delegate = self
} catch {
  print("Unexpected error: \(error).")
}

By default, the Textile instance will manage itself during app life-cycle events as long as you initialize it correctly in your app, meaning your app will be connected to the IPFS network whenever your app requires it.

Get the account display name

NSError *error;
NSString *name = [Textile.instance.profile name:&error];
if (error) {
  // Do something with this error
} else {
  // Success!
}
var error: NSError?
let name = Textile.instance().profile.name(&error)
if (error != nil) {
  // Do something with this error
} else {
  // Success!
}

Subscribe to file updates

// Set the Textile delegate to any object that conforms to the TextileDelegate protocol
Textile.instance.delegate = delegate;

// The delegate can receive callbacks for any event it is interested in, for example
- (void)threadUpdateReceived:(FeedItem *)feedItem {
  if ([feedItem.payload.typeURL isEqualToString:@"/Files"]) {
    // new file!
  }
}
// Set the Textile delegate to any object that conforms to the TextileDelegate protocol
Textile.instance().delegate = delegate

// The delegate can receive callbacks for any event it is interested in, for example
func threadUpdateReceived(_ feedItem: FeedItem) {
  if (feedItem.payload.typeURL == "/Files") {
    // new file!
  }
}

Fetch chronological thread updates

FeedRequest *request = [[FeedRequest alloc] init];
request.thread = @"<thread-id>";
NSError *error;
FeedItemList *feedItemList = [Textile.instance.feed list:request error:&error];
if (error) {
  // Do something with this error
} else {
  // Success!
}
let request = FeedRequest()
request.thread = ""
var error: NSError?
let feedItemList = Textile.instance().feed.list(request, error: &error)
if (error != nil) {
  // Do something with this error
} else {
  // Success!
}

Create a thread

NSError *error;
AddThreadConfig_Schema *schema = [[AddThreadConfig_Schema alloc] init];
schema.preset = AddThreadConfig_Schema_Preset_Blob;
AddThreadConfig *config = [[AddThreadConfig alloc] init];
config.key = @"your.bundle.id.version.Basic";
config.name = @"Basic";
config.type = Thread_Type_Private;
config.sharing = Thread_Sharing_NotShared;
config.schema = schema;
Thread *thread = [Textile.instance.threads add:config error:&error];
if (error) {
  // Do something with this error
} else {
  // Success!
}
var error: NSError?
let schema = AddThreadConfig_Schema()
schema.preset = AddThreadConfig_Schema_Preset.blob
let config = AddThreadConfig()
config.key = "your.bundle.id.version.Basic"
config.name = "Basic"
config.type = Thread_Type.private
config.sharing = Thread_Sharing.notShared
config.schema = schema
let thread = Textile.instance().threads.add(config, error: &error)
if (error != nil) {
  // Do something with this error
} else {
  // Success!
}

Add a file

NSString *threadId = @"<thread-id>";
NSData *jsonData = [@"{ latitude: 48.858093, longitude: 2.294694 }" dataUsingEncoding:NSUTF8StringEncoding];
NSString *dataString = [jsonData base64EncodedStringWithOptions:0];
[Textile.instance.files prepare:dataString threadId:threadId completion:^(MobilePreparedFiles *preparedFiles, NSError *error) {
  if (error) {
    // Do something with this error
  } else {
    NSError *error;
    [Textile.instance.files add:preparedFiles.dir threadId:threadId caption:@"" error:&error];
    if (error) {
      // Do something with this error
    } else {
      // Success!
    }
  }
}];
let threadId = "<thread-id>"
let jsonData = "{ latitude: 48.858093, longitude: 2.294694 }".data(using: .utf8)
if let data = jsonData {
  let dataString = data.base64EncodedString()
  Textile.instance().files.prepare(dataString, threadId: threadId) { (preparedFiles, error) in
    if let files = preparedFiles {
      var filesAddError: NSError?
      Textile.instance().files.add(files.dir, threadId: threadId, caption: nil, error: &filesAddError)
      if (filesAddError != nil) {
        // Do something with this error
      } else {
        // Success!
      }
    } else {
      // Do something with error
    }
  }
}

Files stored on disk

You can add files stored on disk by passing the path information.

NSString *threadId = @"<thread-id>";
NSString *filePath = @"/path/to/mmm-bytes....";
[Textile.instance.files prepareByPath:filePath threadId:threadId completion:^(MobilePreparedFiles *preparedFiles, NSError *error) {
  if (error) {
    // Do something with this error
  } else {
    NSError *addFilesError;
    [Textile.instance.files add:preparedFiles.dir threadId:threadId caption:nil error:&addFilesError];
    if (addFilesError) {
      // Do something with this error
    } else {
      // Success!
    }
  }
}];
let threadId = "<thread-id>"
let filePath = "/path/to/mmm-bytes...."
Textile.instance().files.prepare(byPath: filePath, threadId: threadId) { (preparedFiles, error) in
  if let files = preparedFiles {
    var addFilesError: NSError?
    Textile.instance().files.add(files.dir, threadId: threadId, caption: nil, error: &addFilesError)
    if (addFilesError != nil) {
      // Do something with this error
    } else {
      // Success!
    }
  } else {
    // Do something with error
  }
}

Get a file

NSString *hash = @"some file hash";
NSError *error;
NSString *base64 = [Textile.instance.files data:hash error:&error];
if (error) {
  // Do something with this error
} else {
  // Success!
}
let hash = "<some file hash>"
var error: NSError?
let base64 = Textile.instance().files.data(hash, error: &error)
if (error != nil) {
  // Do something with this error
} else {
  // Success!
}

Example application

The ios-textile repo contains a simple code example you may find useful in your exploration.

API Documentation

The full API documentation for Textile's iOS SDK (ios-textile) can be found at https://textileio.github.io/ios-textile.

Feel free to join the Textile Developer Slack and let us know what you are building. People are always excited to share and learn about new ideas.