AR Development

AR (Augmented Reality) ushered in a new era and enhanced user experience. AR is a blend of the digital and real worlds. Users can experience components like sound, images, and motion along with GPS data to make the view more attractive and informative. Gamers experience a whole new level of gaming when they playing AR games.

Third Rock Techkno is highly experienced in AR development. We develop futuristic apps and games for our clients. Do you have a great concept for a game or an interesting app? Check out the features we have worked on and let’s explore how we can work together!

Our AR Services

  • 1. 2D / 3D content loading on AR environment.
  • 2. Location based AR development
  • 3. Floor / surface detection AR app development
  • 4. Face detection AR app development
  • 5. Update to new technology in AR app development
  • 6. iOS AR App development
  • 7. Android AR app development
  • 8. Maintenance and Update AR app development
  • 9. UI/UX update app development

Our Existing Clients

We cater to a diverse clientele spanning across various industries.

Why Choose Us As Your AR Development Company

Experienced Developers

Our highly-qualified AR development experts specialize in building customized, creative and highly-interactive web and mobile applications. Whether you are a startup or an SME, our experts will get the job done.

Trusted Delivery Methods

We employ the agile methodology to keep you in the loop. Throughout AR development and mobile development, we focus on delivering solutions that meet your business goals, timeline, and budget.

Competitive Rates

Whether it is AR development or mobile development, we offer the most competitive rates on the market. Our personalized services meet different budget needs of our clients from across the globe.

Transparent Work Approach

Our AR development company ensures complete project visibility right from the time you approach us with your needs. We use email, phone, Skype, Slack, and other mediums for regular communication with our clients.

Customer Satisfaction

Our designers, developers, quality analysts, and a project manager – all strive for customer satisfaction. We deliver AR app development services that align with our clients’ needs.

Client Testimonials

Our WORK speaks louder than our WORD. Find out how we helped clients overcome challenges and succeed.

Smoovr

Very good communication at all stages. Always prompt to reply. Excellent quality of work. The team at Third Rock Techkno was communicative, responsive, and accommodating as they produced high-quality work.

Jonathan Wood, Smoovr

Ontime

It was a pleasure working with the TRT team. Prior to contracting this group, I had a system created that was absolutely terrible and poorly developed. I also worked with a few freelancers that couldnt cut it either. TRT was actually able to execute on our concept and have built a truly solid system for our company.

Karl Pierre, Ontime

Highlights Of AR Development

Marker Detection

The marker detection technique is used to display content on the detected marker. Ideally, the marker is a 2D image that can be detected /scanned in the Augmented reality. Marker detection works based on the pre-defined image.

Markerless / Floor Detection

Markerless or floor detection works without a marker. In this case, when we need to display Augmented reality content. That content will be displayed on the floor.

3D Object Detection

3D object detection works as the 3D marker of your object. In this case, you can track your 3D object and display Augmented Reality content.

Face Detection

Face detection is a unique way to display augmented reality. In face detection, your face will be considered as a marker so you can render some content on the face.

Recent AR Development Blogs

26 Oct 2020 | 3 Min Read
Getting started with combine framework

Combine is a new framework, Apple introduced in WWDC 2019. This framework provides a declarative Swift API for processing values over time. Combine allows you to write functional reactive code by providing declarative swift apis. We can compare this framework with RxSwift and RxCocoa. It allows us to process values over a time. Examples of this kind of value are network response, user interface events and other similar types of asynchronous data. There are some basic concepts that you need to understand. * Publisher: Things that produce values * Operator: Things that do work with values * Subscriber: Things that care about values We will explain all 3 points in this blog. Publisher Publishers are the basic provider of data when it is available and required. Publisher which has not any request will not provide any data (But obvious). This protocol has 2 associated types. 1. Output: The types of value it produces 2. Failure: The types of error it could encounter Publisher can emit multiple events: * An Output values of Output type * Completion of publisher * A failure with error having Error type Timer and URLSession is an enhanced type of foundation. Operator Operators are special methods that are called on publishers and return the same or different publishers. It is used to change values like adding, removing and many other operations. You can use multiple operators to perform complex processing. Each operator returns a type that implements the publisher protocol. Below is example of some operator Map Filter RemoveDuplicates Subscriber Subscriber receives values from publisher. Publishers and operators are pointless until someone is listening to the published events. Subscriber confirms following protocols. Subscriber can receive a value of type Input or termination event with either success or Failure. A subscriber receives a stream of value, completions or failure events from a publisher Let’s combine Subscriber and Publisher. Publisher will start delivering value when you call subscribe(_:) on it, passing your subscriber. At that point, publishers send subscriptions to subscribers. Rules of subscription 1. A subscriber can only have one condition. 2. Zero or more values can be published 3. At most one completion will be called Best example of a complete publisher is URLSessionTask Publisher which will complete tasks either with data response or with error response. Whenever error will be thrown, subscribers will end even if it has multiple values to pass through.. Below image will help you to understand the flow between publisher and subscriber. In short, combine is Combine = Publishers + Subscribers + Operators Lets connect Publisher and Subscriber Combine has 2 built in subscribers: Subscribers.Sink and Subscribers.Assign. You can call them either by calling this method on a publisher. sink(receiveCompletion:receiveValue:) to handle new element or completion event in closure. Assign(to:on:) to write new element to a property 1. Create a Just publisher that sends a single value and then completes. Combine has number of build in publishers including, Just 2. Connect a Subscribers.sink subscriber. It will print below. Cancellable First of all in Rx Subscription results in a disposable, which allows you to stop the subscription, Combine does not have this. If you don’t want to receive further updates, you will just de-reference the publisher chain. So apple manages this functionality with Cancellable. Cancellable protocol has a cancel method which frees up any allocated resources. According to documentation, cancellable is protocol that indicates an activity or actions may be cancelled. Benefits of using combine framework 1. Simplified asynchronous code - No more callbacks. 2. Declarative syntax - Easy to read and maintain. 3. Multithreading- You don’t have to worry about it. 4. Built in memory management - No more bugs to carry.

16 Oct 2020 | 6 Min Read
Exploring WidgetKit in iOS 14

Last time we explored the brand new SwiftUI introduced in WWDC19 by building an analog clock [https://www.thirdrocktechkno.com/blog/getting-started-with-swiftui/]. It was really fun to use SwiftUI. Now this year Apple introduced lots of new technologies. Today we will explore the new WidgetKit technology by extending our previous SwiftUI blog. According to Apple, > Widgets are used to show relevant, glanceable content from your app on the iOS Home screen or macOS Notification Center. WidgetKit is available for iOS 14.0+, macOS 11.0+, Mac Catalysts 14.0+. WidgetKit works in a separate target of our main app. So any app that follows the best practices for the app extension can adopt this feature easily. Even though our app is supporting lower versions of iOS, our Widgetkit extension target can be deployed to iOS 14.0+ versions. In this diagram, you can see that WidgetKitExtension is a separate extension in which we are having Widget which is responsible for providing the TimeLine for our widgets to be displayed by the iOS on the home screen (springboard). WidgetKit works in a sense of the timeline. Our app/extension can provide the timeline with our data to be displayed on by the widgetkit on the home screen. For example * Stocks app can update its widget to reflect the new stock prices at the appropriate time. * Clock’s widget can display current time for multiple places. * Calendar’s widget can display upcoming events right on the home screen. * Weather’s widget can display the weather of your selected region. * News’s widget can display the latest news. And so on. As in the diagram, A Widget basically provides a timeline and provides a SwiftUI view for that timeline instance. To provide the timeline, WidgetKit provides a protocol called TimelineProvider (or it can be IntentTimeLineProvider in case of IntentConfiguration). By following these protocol requirements we can provide our full timeline and reload policy to WidgetKit. > A reload policy is used by the WidgetKit to reload the timeline once the current timeline ends or at a custom request from our application or extension. Once we provide the timeline, WidgetKit will call our closure with the timeline entry to collect the new SwiftUI view for the latest entry from the timeline. Clocky Widget. Adjustment in earlier code. Before we start creating the new widget, we first adjust our code we did in the previous article to make easy adoption for our shiny new widget. Since the Timeline protocol has a date: Date requirement, we are moving the Timer publisher from TickHands to our top ContentView so it only depends on the external date dependency. And we extracted the assembly of the clock views from the ContentView to new ClockView so we can share it to our widget extension. And to adapt all the 3 of WidgetFamily which are systemSmall, systemMedium and systemLarge we are creating some variables for the font size and insets. That’s all the changes we need to do. Creating the new target. To create a new widget kit extension called ClockyWidget we need to create a new target within the Xcode project Create new target.Clocky WidgetNow activate the target and Xcode will create a new Folder ClockyWidget with the required files and sample code implementation. Now we modify some basic information for our widget like in below code. @main struct ClockyWidget: Widget { // 1 private let kind: String = "ClockyWidget" public var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in ClockyWidgetEntryView(entry: entry) } // 2 .configurationDisplayName("Clocky Widget") // 3 .description("Displays the current time") } } 1. We provide a kind string for our Static Configuration. 2. We change our Display name to Clocky Widget 3. We provide the description of our widget. Here in ClockyWidget.swift file, all the protocol requirements are generated by the Xcode for us. So we only need to provide some of the data for timeline and our swiftui view from our main application target. To use the source files we need to add those to our widget extension target also. Add target membership of comman files to Widget extensionAll the setup done. Now we can add some timeline entries. // 4 struct ClockyEntry: TimelineEntry { public let date: Date } 4- We create the struct for the TimelineEntry. TimelineEntry protocol has one required property which is date. // 5 struct Provider: TimelineProvider { // 6 public typealias Entry = ClockyEntry // 7 func getSnapshot(in context: Context, completion: @escaping (ClockyEntry) -> Void) { let entry = ClockyEntry(date: Date()) completion(entry) } // 8 func getTimeline(in context: Context, completion: @escaping (Timeline<ClockyEntry>) -> Void) { var entries: [ClockyEntry] = [] // Generate a timeline consisting of 60 entries a second apart, starting from the current date. let currentDate = Date() for hourOffset in 0 ..< 60 { let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)! let entry = ClockyEntry(date: entryDate) entries.append(entry) } // 9 let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } // 10 public func placeholder(in: Context) -> ClockyEntry { ClockyEntry(date: Date()) } } 5. To create the whole timeline we need to follow TimelineProvider protocol. 6. In this we declare that our Entry will be of type ClockEntry. 7. this method is called when our widget is in the widget gallery waiting to be added in the home screen springboard. Here we return our ClockEntry in the completion with the current date for the snapshot. 8. This is the heart of all the widget kit. In this we need to pass the Timeline instance to completion. So for our sample project we create the TimeLineEntries for every seconds for 1 min and append to our entries array. 9. Then we create the Timeline object using our entries array and .atEnd reload policy. That means when in the timeline all the 60 entries get completed, we request WidgetKit to reload our timeline again. 10. Now we pass our timeline to completion. SwiftUI Magic. Now we have our full timeline ready with the reload policy, we need to provide the view to be rendered on the home screen for the specific timeline entry. // 11 struct ClockyWidgetEntryView : View { // 12 var entry: ClockyProvider.Entry // 13 @Environment(\.widgetFamily) var family: WidgetFamily // 14 @ViewBuilder var body: some View { switch family { // 15 case .systemSmall: ClockView( currentDate: entry.date, minuteTickHeight: 8, hourTickHeight: 16, tickInset: 32, font: Font.system(size: 12) ) // 16 case .systemMedium: HStack { ClockView( currentDate: entry.date, minuteTickHeight: 8, hourTickHeight: 16, tickInset: 32, font: Font.system(size: 12) ) ClockView( currentDate: entry.date.convert(to: TimeZone(identifier: "Europe/Berlin")!), minuteTickHeight: 8, hourTickHeight: 16, tickInset: 32, font: Font.system(size: 12) ) } // 17 case .systemLarge: ClockView(currentDate: entry.date) @unknown default: ClockView(currentDate: entry.date) } } } 11. SwiftUI View requires a View protocol to be conformed. So we created the ClockyWidgetEntryView. 12. From the WidgetKit we will get the one entry for every timeline entry we set before. So to accommodate that we are declaring the variable entry: Provider.Entry which is our ClockyEntry. 13. Since Widgets come in 3 sizes, and we are also supporting all sizes, we declare an Environment variable with \.widgetFamily key. 14. We need to switch for all the widget families so we need to declare our body as a @ViewBuilder property. 15. In systemSmall widget family we are only showing one small ClockView. 16. In systemMedium widget family we are showing two clockView side by side with TimeZone difference. 17. In systemLarge widget family we are again showing the one big ClockView. As we had used custom font sizes for our TickText in previous article. We are now adjusting them according to widget family. And that's all. Now we can run our extension and the result is beautiful.

13 Oct 2020 | 4 Min Read
How to get started with RxSwift

Introduction Most programming in the object-oriented era has been imperative. Code tells your program what to do and has many ways to listen to change. However, you must tell the system when something changes. Wouldn’t it be better if you could set things up so the code updates reflect changes automatically ? That's what reactive programming does. Your application reacts to the changes and underlying data without you telling to do so. This makes it easier to focus on the logic at hand rather than maintaining a particular state. You can achieve this in swift using KVO and didSet, but it can be inconvenient to set up. Alternatively there are several frameworks in swift that facilitate reactive programming. The RxSwift library can help you with the way to address that through asynchronous programming. RxSwift and RxCocoa are part of the suite of Reactive Extension(Rx) language tools that span multiple programming languages and platforms. ReactiveX(Rx) introduces a new paradigm that enables writing concise and easily readable code and facilitates powerful architecture like MVVM. It simplifies such a complex problem as handling errors across multiple threads. RxSwift is a framework for interacting with the swift programming language, while RxCocoa is a framework that makes cocoa APIs used in iOS and OS X easier to use with reactive techniques. Basic Components of RxSwift: Observable Sequence Subjects DisposeBag Operators Schedules Observable Sequence: It is a structure which emits a certain value over time. A subscriber subscribes to the observable. We can observe an array, string, HTTP request, text change in UITextField. You can subscribe to an observable sequence by calling subscribe(on:(Event<T>)->()). In RxSwift an event is just an Enumeration Type with three possible states. .next(value: T) ->It emits N number of times an event .error(error: Error) -> The observable emits an error and terminates .completed -> The observable completes its work. Subjects: A subject is a special form of an observable sequence, you can subscribe and dynamically add elements to it. There are currently four different kinds of subjects in RxSwift. * PublishSubject * BehaviourSubject * ReplaySubject * BehaviourReplay (which was Variable) Each type gives us the functions to receive the value change of subscribers when listening or not. DisposeBag: Garbage pickup and removal. It helps automatically deallocate objects from memory (leveraging, ofcourse, Automatic Reference Counting mechanism — ARC). Without a DisposeBag, you’d get one of two results. Either the Observer would create a retain cycle, hanging on to what it’s observing indefinitely, or it could be deallocated, causing a crash. For more : https://github.com/ReactiveX/RxSwift/blob/master/RxSwift/Disposables/DisposeBag.swift Operators: We have a lot of powerful operators supporting us so well such as Map, Flatmap, Filter, DistinctUntilChanged, CombineLatest, etc. Scheduler: The last one is also the most important one. A RxSwift scheduler manages threads before and after the subscriber receives the return value. We can work with schedulers like MainScheduler, CurrentThreadScheduler, SerialDispatchQueueScheduler, ConcurrentDispatchQueueScheduler, OperationQueueScheduler RxSwift Code Example: Here, starting with a very simple example in which we will display the basic details of users from api in tableview. Before getting started you need to install cocoa pods for RxSwift and RxCocoa libraries. So let’s get started. Create a Model: struct User: Codable { var id: Int var name: String var email: String } This model stores basic details like id, name and emailId of the user. We made this model decodable to go from a JSON data object to an actual swift class or struct. Create a function to call API using observable : func fetchData<T: Codable>(url: String) -> Observable<T> { return Observable<T>.create { observer in guard let request = URL(string: url) else { return Disposables.create() } let task = URLSession.shared.dataTask(with: request ) { (data, response, error) in do { let model = try JSONDecoder().decode(T.self, from: data ?? Data()) observer.onNext( model ) } catch let error { observer.onError(error) } observer.onCompleted() } task.resume() return Disposables.create { task.cancel() } } } In this function we are returning Observable of any T type (Observable<T>). Firstly, it takes data from a given url and stores it in the url variable. After that if a given url exists then we are fetching data from the any T type by decoding tham using JSONDecoder and storing it in a variable named model. Our observable variable observer observes the data fetched from the given url and onNext function performs further processing on that . If there is any error , the catch block will call and observer variable’s onError method will call If a task is completed then the observer variable’s onCompleted method will call. For more about URLSession in swift: https://github.com/ReactiveX/RxSwift/blob/master/RxCocoa/Foundation/URLSession%2BRx.swift Create a disposeBag and an observable: let disposeBag = DisposeBag() var users:Observable<[User]>? Bind the data in a tableView: users = fetchData() users?.bind(to: tableView.rx.items(cellIdentifier: "UserCell")) { row, dataSource, cell in guard let cell = cell as? UserCell else { return } cell.setupData(user: dataSource) } .disposed(by: disposeBag) It is binding the data to the tableView directly without calling dataSource methods and reloading tableView again. At the end we are disposing using disposed(by:) function of RxSwift library. Output:

Get in Touch

Is your mind buzzing with ideas?
Let us know about them!

Contact Us