iOS: Issue Importing Calls From Another File - objective-c

I'm still new to Objective-C so I'm having a hard time with this. In my AppController, When a user clicks on one of the ads in my app, then closes the ad and returns to my app, I would like to destroy and recreate the ad (Long story as to why). For some reason though, my code isn't working. There are no errors or warnings, but it doesn't do what I intended it to do. This is what my code looks like:
#import "MoPubManager.h"
......
- (void)applicationWillEnterForeground:(UIApplication *)application
{
MoPubManager *obj = [[MoPubManager alloc] init];
if( obj.adView ) {
[[MoPubManager sharedManager] destroyBanner];
}
[obj.adView refreshAd];
}
_adView, destroy banner, and refresh ad are both in the MoPubManager file, so as you can see I imported the file and turned MoPubManager into an object. (obj.adView was originally just _adView in MoPubManager.h, but I had to switch it to obj.adView to avoid warnings.) I may just be using the wrong calls, I would post the MoPubManager.mm file where the calls originally are but its a full page or two

In the line:
MoPubManager *obj = [[MoPubManager alloc] init];
You are creating a new instance of the MoPubManager class.
Next you are checking whether the adView property of that newly instantiated class is not nil. Unless adView gets populated in the init method of MoPubManager, this will always be nil, so the destroyBanner method will not be called.
However, the destroyBanner method is being called on a sharedManager... indicating a singleton pattern in use. Therefore you should not be creating a new instance as this goes against the reason for using a singleton. (You only ever have one instance of a class when using a singleton - see this for more info)
Without seeing more code, it seems that you should be calling something like:
if( [MoPubManager sharedManager].adView ) {
[[MoPubManager sharedManager] destroyBanner];
}
[[MoPubManager sharedManager].adView refreshAd];

First, what subclass is MoPubManager... It compiles fine? The problem here seems to be that you are creating a new MoPubManager instance, but you are using a singleton to destroy it, and they don't have the same reference. You should use something diferent like:
MoPubManager *obj = [[MoPubManager alloc] init];
if( [MoPubManager sharedManager].adView ) {
[[MoPubManager sharedManager] destroyBanner];
}
[[MoPubManager sharedManager].adView refreshAd];

You are not using correctly the singleton pattern.
try this , maybe will help you
- (void)applicationWillEnterForeground:(UIApplication *)application
{
MoPubManager *obj = [MoPubManager sharedManager];
if( obj.adView ) {
[obj destroyBanner];
}
[obj.adView refreshAd];
}

Related

Open ears text to speech (voice) not working when getting string from another class/controller (IOS, Objective c)

I am very new to objective c and OpenEars so please forgive me if I have some messy code and if I am lost in very simple problem.
Anyhow, I have two controllers in this application. The first being the default ViewController and the second one being a new one that I made called ReplyManagerController.
The code in the ViewController basically uses the one in the tutorial with some (maybe more some) changes.
EDIT:
The app is supposed to be a basic app where a user says something and the app replies.
But the original problem was that I could not get the string to display or TTS to work when my ViewController got it's string from another class/controller.
The answer in my below mentions that it was probably because my other class was calling my ViewController without the self.fliteController initialized.
How would I initialize the ViewController with self.fliteController initialized?
ViewController.m
- (void) pocketsphinxDidReceiveHypothesis:(NSString *)hypothesis recognitionScore:(NSString *)recognitionScore utteranceID:(NSString *)utteranceID {
NSString *strResult = hypothesis; //speech to text to string
ReplyManager* replyObject = [[ReplyManager alloc] init];
[replyObject speechResult:(NSString*)strResult viewController:self];
}
- (void) getReply:(NSString*)replyStr{
[self.fliteController say:replyStr withVoice:self.slt];
[self updateText:replyStr];
}
- (IBAction)updateText:(NSString*)replyStr{
labelOne.text = replyStr;
labelOne.adjustsFontSizeToFitWidth = YES;
labelOne.minimumFontSize = 0;
}
Any help will be great! Thanks!
ReplyManager.m
- (void) speechResult:(NSString*)strResult {
NSString *replystr;
NSString *greetings = #"Hi!";
NSString *sorry = #"Sorry I didn't catch that?";
ViewController* getReply = [[ViewController alloc] init];
if ([strResult isEqualToString:#"HELLO"])
{
replystr = greetings;
[getReply getReply:(NSString*)replystr];
}
else
{
replystr = sorry;
[getReply getReply:(NSString*)replystr];
}
}
EDIT 2:
viewDidLoad Method
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.fliteController = [[OEFliteController alloc] init];
self.slt = [[Slt alloc] init];
self.openEarsEventsObserver = [[OEEventsObserver alloc] init];
[self.openEarsEventsObserver setDelegate:self];
}
ViewController* getReply = [[ViewController alloc] init];
Here you init a new ViewController which does not have self.fliteController defined most likely. You need to reuse previos controller, for example like this:
[replyObject speechResult:(NSString*)strResult viewController:self];
So you can use already initialized viewController later. Overall it is better to initialize objects like viewController or replyController beforehand, not inside callback methods.
It sounds like a timing issue where you're trying to use fliteController before it's been initialized.
In your ViewController class, where do you assign a value to the fliteController property? In an initializer? -(void)viewDidLoad?
In ReplyManagerController add:
ViewController* getReply = [[ViewController alloc] init];
// Add these lines
NSLog(getReply.fliteController); // Is this nil?
[getReply.view layoutIfNeeded];
NSLog(getReply.fliteController); // Is it still nil?
Does the above fix the problem? If so, you're probably initializing fliteController in -(void)viewDidLoad. What's the result of the two NSLog statements?

Handling CLLocationManager delegate from another class

I have 2 classes as NSObject subclasses:
1st class is more likely act as adapter. It send data to Class2 for process async task. When delegaton fired I would like to post back data to adaptor class.
In adaptor class:
Class2 *cls = [[Class2 alloc] init];
[ftc fetchLocation];
In Class2.m
-(void)fetchLocation{
if(IS_OS_8_OR_LATER) {
[self.locationManager requestAlwaysAuthorization];
}
self.locationManager = [[CLLocationManager alloc] init];
if ([CLLocationManager locationServicesEnabled]){
NSLog(#"Enable");
}
self.locationManager.delegate =self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
[self.locationManager startUpdatingLocation];
}
When I call fetch-location method from adaptor, it really calls and reads lines, but after that, Class2 disappears and gone back to Adapter class without waiting delegation (didUpdateLocations)
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
NSString *latitude = [NSString stringWithFormat:#"%f",self.locationManager.location.coordinate.latitude];
NSString *longtitude = [NSString stringWithFormat:#"%f",self.locationManager.location.coordinate.longitude];
NSString *altitude = [NSString stringWithFormat:#"%f",self.locationManager.location.altitude];
NSString *speed = [NSString stringWithFormat:#"%f",self.locationManager.location.speed];
NSDictionary *locationDictionary = #{#"latitude":latitude,#"longtitude":longtitude,#"altitude":altitude,#"speed":speed};
if (locations.count >0 && [locations isKindOfClass:[NSArray class]]) {
[self.delegate userLocationHasUpdated:self :locationDictionary];
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
return;
}
}
But if I just run Class2 and remove adapter from compile (with first initialiser) it runs as expected, How can I achieve to handle delegation methods from another class that fired ?
Best Regards.
You have several options, really. One could be making your second class a property of your first class (singleton pattern would fit nice here, I guess). Then you can either declare a protocol in your second class and notify your first class via delegate methods (non-singleton implementation) or use NSNotificationCenter to post a notification (singleton implementation).
The second option would be to pass a block with completion handler to the second class. You could declare your method in the second class like this, for example (adjust return type and arguments of the block, if needed):
- (void)updateLocationWithCompletionHandler:(void (^)(void))completion;
Implement it so that you call the completion block after you get the geolocation update results.
And call it from the first class like:
[self.secondClass updateLocationWithCompletionHandler:^
{
// Your completion code here.
}];
Hope this helps (sorry, didn't check the code in Xcode, get rid of typos, if any).
Possible duplicate of iOS CLLocationManager in a separate class. You have to create a singleton class for to get the location if you want to have seperate class for handing the location manager. You will find the guidance from the shared link

Magical Record object for current thread

I'm using Magical Record 2.3.0 beta 5 and I have troubles understanding how to get my NSManagedObjects for the current thread. I have a long running NSOperation where I need my PSPlayer (NSManagedObject).
When I init the NSOperation, I keep an id of my PSPlayer and re-fetch the same object in the operation's main method. According to Apple that the way to do it.
#implementation TAPlayerUpdateOperation
- (instancetype)initWithPlayer:(PSPlayer *)player;
{
self = [super init];
if (self) {
self.playerMD5Id = player.md5Id;
}
}
- (void)main
{
#autoreleasepool {
__block BOOL keepUpdating = YES;
PSPlayer *player = [[PSPlayer MR_findAllWithPredicate:[NSPredicate predicateWithFormat:#"md5Id == %#", self.playerMD5Id]] firstObject];
NSLog(#"player.md5Id = %#", player.md5Id);
// rest of my operation logic
}
}
#end
When I run my app with -com.apple.CoreData.ConcurrencyDebug 1, I get a crash when accessing the property in the NSLog statement.
What is the correct way to get my NSManagedObject so that it is safe for the current thread?
I've pinned the problem down to the following snippet where it crashes as well.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PSPlayer *player =[[PSPlayer MR_findAll] firstObject];
NSLog(#"player = %#", player.name);
});
cheers,
Jan
You need to ensure that everything is saved and merged before the fetch would work. If you're using MR then it's better to take the managed object and call inContext: on it supplying the other context and have it do the work (it also avoids a predicate).
I expect the crash is because you use player.md5Id instead of self.playerMD5Id so you're accessinh the managed object on the wrong thread.

Cocoa Multiple Window Controllers

I have a Cocoa app that uses automatic reference counting and does not use core-data (not document-based) and I want to be able to create multiple instances of a window I have defined in a nib file.
I currently have this in my AppDelegate:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
// for slight performance bump, we assume that users usually have 1 session open.
sessionWindowControllers = [[NSMutableArray alloc] initWithCapacity:1];
}
- (void) awakeFromNib {
// on start, we create a new window
[self newSessionWindow:nil];
}
- (IBAction)newSessionWindow:(id)sender {
SessionWindowController *session = [[SessionWindowController alloc] initWithWindowNibName:#"SessionWindow"];
//add it to the array of controllers
[sessionWindowControllers addObject:session];
[session showWindow:self];
}
SessionWindowController is a subclass of NSWindowController.
but when I run it, I get the runtime error
LayoutManagement[30415] : kCGErrorIllegalArgument:
_CGSFindSharedWindow: WID 11845 Jun 8 18:18:05 system-process LayoutManagement[30415] : kCGErrorFailure: Set a breakpoint #
CGErrorBreakpoint() to catch errors as they are logged. Jun 8
18:18:05 system-process LayoutManagement[30415] :
kCGErrorIllegalArgument: CGSOrderFrontConditionally: Invalid window
Is using NSMutableArray even a good way to manage multiple windows, or is there a better design pattern? Thanks!
Ans. kindly provided by Ben Flynn:
I put the
sessionWindowControllers = [[NSMutableArray alloc] initWithCapacity:1];
in applicationDidFinishLaunching, but since awakeFromNib is called first, we are trying to add an instance of session to the array before it even exists.
Solution: put array init inside the awakeFromNib before we make our first window.
- (void) awakeFromNib {
sessionWindowControllers = [[NSMutableArray alloc] initWithCapacity:1];
[self newSessionWindow:nil];
}

NSFilePresenter methods never get called

I'm trying to write a simple (toy) program that uses the NSFilePresenter and NSFileCoordinator methods to watch a file for changes.
The program consists of a text view that loads a (hardcoded) text file and a button that will save the file with any changes. The idea is that I have two instances running and saving in one instance will cause the other instance to reload the changed file.
Loading and saving the file works fine but the NSFilePresenter methods are never called. It is all based around a class called FileManager which implements the NSFilePresenter protocol. The code is as follows:
Interface:
#interface FileManager : NSObject <NSFilePresenter>
#property (unsafe_unretained) IBOutlet NSTextView *textView;
- (void) saveFile;
- (void) reloadFile;
#end
Implementation:
#implementation FileManager
{
NSOperationQueue* queue;
NSURL* fileURL;
}
- (id) init {
self = [super init];
if (self) {
self->queue = [NSOperationQueue new];
self->fileURL = [NSURL URLWithString:#"/Users/Jonathan/file.txt"];
[NSFileCoordinator addFilePresenter:self];
}
return self;
}
- (NSURL*) presentedItemURL {
NSLog(#"presentedItemURL");
return self->fileURL;
}
- (NSOperationQueue*) presentedItemOperationQueue {
NSLog(#"presentedItemOperationQueue");
return self->queue;
}
- (void) saveFile {
NSFileCoordinator* coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
NSError* error;
[coordinator coordinateWritingItemAtURL:self->fileURL options:NSFileCoordinatorWritingForMerging error:&error byAccessor:^(NSURL* url) {
NSString* content = [self.textView string];
[content writeToFile:[url path] atomically:YES encoding:NSUTF8StringEncoding error:NULL];
}];
}
- (void) reloadFile {
NSFileManager* fileManager = [NSFileManager defaultManager];
NSFileCoordinator* coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
NSError* error;
__block NSData* content;
[coordinator coordinateReadingItemAtURL:self->fileURL options:0 error:&error byAccessor:^(NSURL* url) {
if ([fileManager fileExistsAtPath:[url path]]) {
content = [fileManager contentsAtPath:[url path]];
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.textView setString:[[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding]];
});
}
// After this I implement *every* method in the NSFilePresenter protocol. Each one
// simply logs its method name (so I can see it has been called) and calls reloadFile
// (not the correct implementation for all of them I know, but good enough for now).
#end
Note, reloadFile is called in applicationDidFinishLaunching and saveFile gets called every time the save button is click (via the app delegate).
The only NSFilePresenter method that ever gets called (going by the logs) is presentedItemURL (which gets called four times when the program starts and loads the file and three times whenever save is clicked. Clicking save in a second instance has no noticeable effect on the first instance.
Can anyone tell me what I'm doing wrong here?
I was struggling with this exact issue for quite a while. For me, the only method that would be called was -presentedSubitemDidChangeAtURL: (I was monitoring a directory rather than a file). I opened a technical support issue with Apple, and their response was that this is a bug, and the only thing we can do right now is to do everything through -presentedSubitemDidChangeAtURL: if you're monitoring a directory. Not sure what can be done when monitoring a file.
I would encourage anyone encountering this issue to file a bug (https://bugreport.apple.com) to encourage Apple to get this problem fixed as soon as possible.
(I realize that this is an old question, but... :) )
First of all, I notice you don't have [NSFileCoordinator removeFilePresenter:self]; anywhere (it should be in dealloc).
Secondly, you wrote:
// After this I implement *every* method in the NSFilePresenter protocol. Each one
// simply logs its method name (so I can see it has been called) and calls reloadFile
// (not the correct implementation for all of them I know, but good enough for now).
You're right: it's the incorrect implementation! And you're wrong: it's not good enough, because it's essential for methods like accommodatePresentedItemDeletionWithCompletionHandler: which take a completion block as a parameter, that you actually call this completion block whenever you implement them, e.g.
- (void) savePresentedItemChangesWithCompletionHandler:(void (^)(NSError * _Nullable))completionHandler
{
// implement your save routine here, but only if you need to!
if ( dataHasChanged ) [self save]; // <-- meta code
//
NSError * err = nil; // <-- = no error, in this simple implementation
completionHandler(err); // <-- essential!
}
I don't know whether this is the reason your protocol methods are not being called, but it's certainly a place to start. Well, assuming you haven't already worked out what was wrong in the past three years! :-)