Converting a CocoaPod to TypeScript without access to a viewController: A step-by-step guide

While exploring a tutorial by Nathan Walker on egghead.io, I gained new skills and decided to put them into practice. As a result, I started the conversion process for implementing the material-snackbar pod.

Unfortunately, this pod does not provide access to the UIView or viewController directly (it's within a manager). Can you recommend a way for me to add it to appWindow.rootViewController?

The original code snippet:

MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
message.text = @"How much wood would a woodchuck chuck if a woodchuck could chuck wood?";
[MDCSnackbarManager showMessage:message];

My TypeScript code implementation:

constuctor(){
    this._message = MDCSnackbarMessage.alloc().init(); 
}

public showMessage(m:string){
    this._message.text = m;
    MDCSnackbarManager.showMessage(this._message)
}

Despite my efforts, although everything seems to work fine, nothing appears in my app when I trigger it from the app controller. Therefore, my first instinct is to dive deeper into the MDCSnackBarManager code to find a way to specify the container. Fortunately, I found this solution:

(void)setPresentationHostView:(UIView *)hostView {
  NSAssert([NSThread isMainThread], @"setPresentationHostView must be called on main thread.");
  MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
  manager.presentationHostView = hostView;
}

With this information in mind, I attempted the following approach:

MDCSnackbarManager.setPresentationHostView(rootVC());
const rootVC = function(){
    let appWindow = UIApplication.sharedApplication.keyWindow;
    return appWindow.rootViewController;
}

Unfortunately, it crashes with the error message provided below. How can I ensure that the manager/messages are properly added to the root view?

*** JavaScript call stack:
    (
        0   UIApplicationMain@[native code]
        1   start@file:///app/tns_modules/tns-core-modules/application/application.js:251:26
        2   bootstrapApp@file:///app/tns_modules/nativescript-angular/platform-common.js:68:28
        3   bootstrapModule@file:///app/tns_modules/nativescript-angular/platform-common.js:56:26
        4   anonymous@file:///app/main.js:4:57
        5   evaluate@[native code]
        6   moduleEvaluation@:1:11
        7   @:7:50
        8   promiseReactionJob@:1:11
    )
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationControllerImpl bounds]: unrecognized selector sent to instance 0x7ff366920a00'
    *** First throw call stack:
    (
        0   CoreFoundation                      0x000000010e7f9d4b __exceptionPreprocess + 171
        1   libobjc.A.dylib                     0x000000010e25b21e objc_exception_throw + 48
        2   CoreFoundation                      0x000000010e869f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
        3   CoreFoundation                      0x000000010e77f005 ___forwarding___ + 1013
        4   CoreFoundation                      0x000000010e80ca08 __forwarding_prep_1___ + 120
        5   MaterialComponents                  0x000000010aced0d4 -[MDCSnackbarManagerInternal activateOverlay:] + 612
        6   MaterialComponents                  0x000000010acebeeb -[MDCSnackbarManagerInternal displaySnackbarViewForMessage:] + 1163
        7   MaterialComponents                  0x000000010aceba40 -[MDCSnackbarManagerInternal showNextMessageIfNecessaryMainThread] + 496
        8   MaterialComponents                  0x000000010aced917 -[MDCSnackbarManagerInternal showMessageMainThread:] + 487
        9   MaterialComponents                  0x000000010aceec34 __34+[MDCSnackbarManager showMessage:]_block_invoke + 84
        10  libdispatch.dylib                   0x000000010f4ff808 _dispatch_call_block_and_release + 12
        11  libdispatch.dylib                   0x000000010f52112e _dispatch_client_callout + 8
        12  libdispatch.dylib                   0x000000010f5084fb _dispatch_main_queue_callback_4CF + 1054
        13  CoreFoundation                      0x000000010e7bde49 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
        14  CoreFoundation                      0x000000010e78337d __CFRunLoopRun + 2205
        15  CoreFoundation                      0x000000010e782884 CFRunLoopRunSpecific + 420
        16  GraphicsServices                    0x0000000111619a6f GSEventRunModal + 161
        17  UIKit                               0x000000010c015c68 UIApplicationMain + 159
        18  NativeScript                        0x000000010b48797d ffi_call_unix64 + 85
        19  ???                                 0x000000012a5fdf70 0x0 + 5005893488
    )
Mar 27 16:50:04 PODMB0079 SpringBoard[5820]: [KeyboardArbiter] HW kbd: Failed to set (null) as keyboard focus
Mar 27 16:50:04 PODMB0079 com.apple.CoreSimulator.SimDevice.CB2CCBE6-20D1-4283-908C-2232692E7AC0.launchd_sim[5804] (UIKitApplication:org.nativescript.podtest[0x8461][7291]): Service exited due to Abort trap: 6

Answer №1

I made the mistake of passing the root viewController instead of the view itself to the method. The correct approach is as follows:

MDCSnackbarManager.setPresentationHostView(rootVC().view); //lesson learned
const rootVC = function(){
    let appWindow = UIApplication.sharedApplication.keyWindow;
    return appWindow.rootViewController;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having a problem with file uploads in node.js using multer. The variables req.file and req.files are always coming

I am encountering an issue with uploading a file to my server, as both req.file and req.files are consistently undefined on my POST REST endpoint. The file I'm attempting to upload is a ".dat" file, and my expectation is to receive a JSON response. ...

Create a JavaScript object containing placeholders and another JavaScript object that holds the substitutions to be used

I have a placeholder object named ${var_name} { "name": "${title}", "description": "${description}", "provider": { "@type": "Organization" }, "hasInstance": [ ...

Discovering Typescript's property data type using reflection during program execution时间。

After transpiling TypeScript code to JavaScript, it is commonly understood that TypeScript type information gets lost and features such as reflection become very restricted. Since we rely on JavaScript reflection at runtime, the level of understanding rega ...

Generating a Radio Button Label on-the-fly using Angular 8 with Typescript, HTML, and SCSS

Struggling with generating a radio button name dynamically? Looking to learn how to dynamically generate a radio button name in your HTML code? Check out the snippet below: <table> <td> <input type="radio" #radio [id]="inputId" ...

How is it possible that this does not trigger a compile error? (Mongoose, Typescript, MongoDB)

I am in the process of setting up a MERN project in Typescript and I have come across something that puzzles me. Despite my expectations, there is no compilation error in TS with the following code: Here's the model snippet: import { Document, Schema ...

How to apply a CSS class to an element when hovering in Vue, without the need for data

Within a Vue component, there exists a menu structured as follows: <ul class="menu-outer-wrapper"> <li><a href="/foo-1">Foo 1</a></li> <li class="has-children"> <a href="/foo ...

Issue: Failed to locate module @angular/core

When attempting to run an Angular 4 application, I consistently encounter the following error: ERROR in Could not resolve module @angular/core There are no additional errors present. There are no dependency issues whatsoever as @angular/core is located i ...

NestJS Error TS2339: The property "buffer" is not found on the type File

Within my NestJs application, I have a file being returned from a controller endpoint with the following structure: const file = { fieldname: "file", originalname: "filename.png", encoding: "7bit", mimetype: "imag ...

Storing a chosen avatar in a database: A step-by-step guide

I am looking to display a selection of 10 avatars on my website for users to choose from. There will be no option for users to upload their own avatar. Users will simply click on the avatar image they want and then click the "done" button. The selected ava ...

Getting a file object with v-file-input in Nuxt.js

For my Nuxt.Js apps, I utilized Vuetify.js as the UI framework. In order to obtain the file object when uploading files, I incorporated the v-file-input component from Vuetify.js and wrote the following code snippet: <template> <div> ...

Tallying the number of words delimited by a comma

Here is how my counter function is structured: function count() { var value = ids.val(); return (value == '') ? 0 : value.replace(/\s,?|,$/g, '').split(',').length; } After checking the returned value, data is ...

Tips for adding fixed labels to ng2-charts bar graphs

I am currently using ng2-charts and have an array of data. The challenge I am facing is that when I only have data for Tuesday and Wednesday, the chart only displays those two days. However, I would like the x-axis to remain static, showing all days of the ...

Incorporating an array attribute into a current array of elements

I am currently attempting to incorporate the days of the week into an existing array of objects. To give you a visual representation, check out this image: https://i.stack.imgur.com/0jCBF.png After filtering my array to only yield 7 results, I aim to assi ...

When utilizing Google Analytics in conjunction with Next.Js, encountering the error message "window.gtag is not

Encountering an error on page load with the message: window.gtag is not a function Using Next.js version 14.0.4. All existing solutions seem to hinder data collection, preventing the website from setting cookie consent correctly. I am uncertain about the ...

Is there a way to turn off vue.js transitions specifically for testing purposes?

I'm utilizing a vue.js component with the <transition> element for show/hide animations. However, I want to disable the animation for faster testing. How can I achieve this? The solution proposed is * { transition: none !important } in this lin ...

Guide to switching content within a DIV when the up and down buttons are pressed using JavaScript and jQuery

I have a functional code with a timeline where each event is connected to the other. There are buttons to delete and copy data, but I want to implement functionality for swapping elements when the up or down button is clicked. I have provided a sample code ...

Simultaneously, two identical messages arrived in the form of push notifications via FCM

I have been working on implementing WebPush notifications using Vue.js and FCM. However, when testing the functionality, I am facing an issue where instead of receiving just one notification from Firebase, TWO IDENTICAL PUSH NOTIFICATIONS are being receive ...

Implement dynamic routerLink binding with Angular 11

Having a value containing routerLink and queryParams, I am attempting to bind it in the HTML. anchorValue : string = `<a [routerLink]="['../category/new ']" [queryParams]="{ query: 'category' }" routerLinkActive = ...

The SEMrush API is not displaying an 'Access-Control-Allow-Origin' header on the requested resource

When attempting to utilize the SEMrush API, I made a request using jQuery as shown below: $(document).ready(function() { $.get( 'https://api.semrush.com', { type: 'phrase_this', key: ' ...

What causes AsyncStorage to lose one value while another value remains intact?

My last session id is stored using AsyncStorage, but for some reason it loses a specific value and I can't figure out why. I created an app that should automatically select the last chosen group on startup. However, after restarting the app, AsyncSto ...