I am trying to develop an iPhone app using xcode13 with iPhone 11 simulator. I used Xcode template to create a basic app. Now I created a new class (not derived from UIViewController) and tried to get orientation notifications, but I am getting nothing. I tried to add the same code on class that derived from UIViewController and it worked. why ? why ?
Why it is only working from the UIViewController's derived class?
Can I make it work from a class that isn't derived from UIViewController ?
here is my code that is not working :
main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Orientation/Orientation.h"
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
#autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
NSLog(#"Hello world !");
OrientationService * os = [[OrientationService alloc] init];
[os onStart];
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
Orientation/Orientation.h
#ifndef Orientation_h
#define Orientation_h
#interface OrientationService : NSObject {
NSInteger * orientation_state;
}
- (void) onStart;
- (void) orientationStateDidChange:(NSNotification*) notification;
#end
Orientation/Orientation.m
#endif /* Orientation_h */
#import <Foundation/Foundation.h>
#import "Orientation.h"
#import <UIKit/Uikit.h>
#implementation OrientationService
-(void) orientationStateDidChange:(NSNotification*) notification {
NSLog(#"got notified");
}
-(instancetype)init{
self = [super init];
NSLog(#"OrientationService alloc");
return self;
}
-(void)onStart{
NSLog(#"starting orientation service");
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationStateDidChange:) name:(UIDeviceOrientationDidChangeNotification) object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
#end
I spent so long on this but it just hit me! It's because os in main() isn't being retained in memory. Instead, either implement the functionality in the App Delegate, or retain an instance of your OrientationService object in the App Delegate. For example:
AppDelegate.h
#import <UIKit/UIKit.h>
#include "Orientation.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) OrientationService *os;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
#synthesize os;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
os = [[OrientationService alloc] init];
[os onStart];
return YES;
}
#end
Related
Note: I am new to Objective C
I have implemented the CXCallObserverDelegate callChanged delegate in my custom React Native module but it is not invoked when i receive a VOIP call
In didFinishLaunchingWithOptions of AppDelegate
CallManager *manager = [CallManager new];
[manager someMethod:#"Hoola"]; // sending a test string to print
In CallManager.m
#import "CallManager.h"
#import "RNCallKeep.h"
#implementation CallManager
RCT_EXPORT_MODULE();
-(void)someMethod: (NSString *)someString
{
NSLog(#"Hello world callObserver %#", someString); // Hoola string gets printed here means this method is working
CXCallObserver *callObserver = [[CXCallObserver alloc] init];
self.callObserver = callObserver;
[callObserver setDelegate:(id)self queue:nil];
}
-(void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call {
NSLog(#"Hello world callObserver"); // this doesnt get printed when call is received or status changes
}
#end
In my CallManager.h file
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <CallKit/CallKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface CallManager : NSObject<RCTBridgeModule, CXCallObserverDelegate>
#property (atomic, strong) CXCallObserver *callObserver;
- (void)someMethod: (NSString *)someString;
#end
NS_ASSUME_NONNULL_END
App is compiling fine and launching and performing all things but when I receive a VOIP call and CallKIT UI is invoked, i don't get call status changed events on accept or reject. Note that NSLogs are printed correctly, i put them there for debug and they are working.
//
// AppDelegate.m
//
#import "AppDelegate.h"
#import "MainViewController.h"
#import "SetupViewController.h"
#import <Cordova/CDVPlugin.h>
#import "NSObject+Utils.h"
#import "WebProjectSetupHelper.h"
#import "WebProjectSetupHelperDelegate.h"
#import "LoadingView.h"
#import "AppDelegate.h"
#import "MainViewController.h"
#import "NSObject+Utils.h"
#import "DeviceModelInfo.h"
#import "UIDevice+System.h"
#import "Alert.h"
#interface AppDelegate () <WebProjectSetupHelperDelegate>
#property (nonatomic, strong) WebProjectSetupHelper *helper;
#property (nonatomic, strong) LoadingView *loadingView;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self createItemsWithIcons];
// determine whether we've launched from a shortcut item or not
UIApplicationShortcutItem *item = [launchOptions valueForKey:UIApplicationLaunchOptionsShortcutItemKey];
if (item) {
NSLog(#"We've launched from shortcut item: %#", item.localizedTitle);
} else {
NSLog(#"We've launched properly.");
}
return YES;
}
I am using this code in my App Delegate but on the line that contains "[self createItemsWithIcons];", I get an error that says "No visible #interface for 'AppDelegate' declares the selector 'createItemsWithIcons'".
Any idea what I am doing wrong? I am trying to add quick actions with 3D touch to my app.
Update! I got that issue resolved. Now my next question is from my AppDelegate, how can I run code that is in different file? In the "www" folder there is a file that ends in .js. In that file, there is javascript code that I want to run. Any Ideas on how to call that file?
You have missed to add implementation for createItemsWithIcons method.
https://github.com/versluis/3D-Touch/blob/master/3D%20Touch/AppDelegate.m
If you are working with 3D-Touch sample, then add this code to AppDelegate:
- (void)createItemsWithIcons {
// create some system icons (doesn't work)
// UIApplicationShortcutIcon *loveIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeLove];
// UIApplicationShortcutIcon *mailIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeMail];
// UIApplicationShortcutIcon *prohibitIcon = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeProhibit];
// icons with my own images
UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithTemplateImageName:#"iCon1"];
UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:#"iCon2"];
UIApplicationShortcutIcon *icon3 = [UIApplicationShortcutIcon iconWithTemplateImageName:#"iCon3"];
// create several (dynamic) shortcut items
UIMutableApplicationShortcutItem *item1 = [[UIMutableApplicationShortcutItem alloc]initWithType:#"com.test.dynamic" localizedTitle:#"Dynamic Shortcut" localizedSubtitle:#"available after first launch" icon:icon1 userInfo:nil];
UIMutableApplicationShortcutItem *item2 = [[UIMutableApplicationShortcutItem alloc]initWithType:#"com.test.deep1" localizedTitle:#"Deep Link 1" localizedSubtitle:#"Launch Nav Controller" icon:icon2 userInfo:nil];
UIMutableApplicationShortcutItem *item3 = [[UIMutableApplicationShortcutItem alloc]initWithType:#"com.test.deep2" localizedTitle:#"Deep Link 2" localizedSubtitle:#"Launch 2nd Level" icon:icon3 userInfo:nil];
// add all items to an array
NSArray *items = #[item1, item2, item3];
// add this array to the potentially existing static UIApplicationShortcutItems
NSArray *existingItems = [UIApplication sharedApplication].shortcutItems;
NSArray *updatedItems = [existingItems arrayByAddingObjectsFromArray:items];
[UIApplication sharedApplication].shortcutItems = updatedItems;
}
I'm new to development and been trying to figure this out,but after trying various different solutions, I'm still unable to get the result I'm looking for.
I would like to update the UILabel in a ViewController from another class.
here is a little demo program that I cannot get to work.
I have a view controller which has 3 UILabels, one is updated from the viewDidLoad and the other two I would like to update from the other class called Hello which is called from ViewController, I can the see the class is being called correctly as the console is logging the NSLog entry but I cannot get the syntax for updating the UILabel.
Thanks in advance.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (nonatomic, retain) IBOutlet UILabel *firstLabelBox;
#property (nonatomic, retain) IBOutlet UILabel *secondLabelBox;
#property (nonatomic, retain) IBOutlet UILabel *thirdLabelBox;
#end
ViewController.m
#import "ViewController.h"
#import "Hello.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize firstLabelBox;
#synthesize secondLabelBox;
#synthesize thirdLabelBox;
- (void)viewDidLoad {
[super viewDidLoad];
firstLabelBox.text=#"Hello";
[Hello updatedisplay];
[Hello getStringToDisplay];
}
#end
Hello.h
#import <Foundation/Foundation.h>
#class ViewController;
#interface Hello : NSObject
+(void)updatedisplay;
+(void) getStringToDisplay;
#end
Hello.m
#import "Hello.h"
#import "ViewController.h"
#implementation Hello
+ (void)updatedisplay
{
NSLog(#"NewClass - updatedisplay");
ViewController *labelupdate02 = [[ViewController alloc]init];
labelupdate02.secondLabelBox.text = #"Apple";
}
+ (void) getStringToDisplay
{
NSLog(#"Inside getString function - updatedisplay");
ViewController *labelupdate03 = [[ViewController alloc]init];
labelupdate03.thirdLabelBox.text = #"World";
}
#end
First update method of Hello class
+ (void)updatedisplay
{
NSLog(#"NewClass - updatedisplay");
[[NSNotificationCenter defaultCenter] postNotificationName:#"CHANGE_SECOND_LABEL" object:nil];
}
+ (void) getStringToDisplay
{
NSLog(#"Inside getString function - updatedisplay");
[[NSNotificationCenter defaultCenter] postNotificationName:#"CHANGE_THIRD_LABEL" object:nil];
}
And then update viewDidLoad()
- (void)viewDidLoad
{
[super viewDidLoad];
firstLabelBox.text=#"Hello";
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(secondLabel) name:#"CHANGE_SECOND_LABEL" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(thirdLabel) name:#"CHANGE_THIRD_LABEL" object:nil];
[Hello updatedisplay];
[Hello getStringToDisplay];
}
Implement below methods in ViewController.m.
- (void)secondLabel
{
secondLabelBox.text = #"Apple";
}
- (void)thirdLabel
{
thirdLabelBox.text = #"World";
}
Ive been hitting the wall for two days on this hard (but simple for you) problem.
The problem is as follows:
I am posting a notification in the appdelegate
I am attempting to receive that notification in a viewcontroller but I cannot receive it.
Here is the code for this.
In the appdelegate.h
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) NSString * someString;
#end
In the appdelegate.m
#import "AppDelegate.h"
#import "SomeContextExample.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
self.someString = #"Hello!";
NSDictionary * userInfo = #{SomeContextExampleRef : self.someString};
[[NSNotificationCenter defaultCenter] postNotificationName:#"SomeContextExample"
object:nil
userInfo:userInfo];
return YES;
}
The "SomeContextExampleRef" is coming from a .h file as follows:
#ifndef SampleNotWorking_SomeContextExample_h
#define SampleNotWorking_SomeContextExample_h
#define SomeContextExampleRef #"SomeContextExampleRef"
#endif
Finally, in the viewController.m:
#import "ViewController.h"
#import "SomeContextExample.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] addObserverForName:#"SomeContextExample"
object:nil
queue:mainQueue
usingBlock:^(NSNotification *note)
{
NSLog(#"got the notification!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! %#", note.userInfo);
}];
}
My full code is attached here:
https://github.com/moomoo23/SampleNotWorking
Thank you for helping a beginner!
Try posting your notification when you are confident your "ViewController" object has instantiated and/or come into view. E.G. why not try it out by putting it into an "IBAction" method fired by some UIButton?
The observing view controller may or may not (more likely not in your case) be existing at the end of "application:didFinishLaunchingWithOptions:" in your app delegate.
Another alternative is to post the notification after a delay using the scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: method.
Now, conceptually, why would you post a notification when the appFinsihedLaunching?.... just curious.... e
I'm having strange problem, trying to call my delegate - it never gets called. As i understand ,delegate never gets set. i'm using ARC.
CueCreateDelegate.h
#import <Foundation/Foundation.h>
#class CueCreateDelegate;
#protocol CueCreDelegate <NSObject>
- (void)CueCreatedCall;
#end
#interface CueCreateDelegate : NSObject
#property (nonatomic, assign) id <CueCreDelegate> delegate;
-(void)CueCreated;
- (void) setdelegate:(id<CueCreDelegate>) delegates; //for testing
#end
CueCreateDelegate.m
CueCreated is called from another class and it prints the bad news...
#import "CueCreateDelegate.h"
#implementation CueCreateDelegate
#synthesize delegate ;
- (void) setdelegate:(id<CueCreDelegate>) delegates{
delegate = delegates;
}
-(void)CueCreated{
if ([delegate respondsToSelector:#selector(CueCreatedCall)]) {
[delegate CueCreatedCall];
}
else{
NSLog(#"Delegate method not getting called...%#",delegate);
}
}
#end
MatrixViewController.h
#import <UIKit/UIKit.h>
#import "CueCreateDelegate.h"
#interface MatrixViewController : UIViewController<UIGestureRecognizerDelegate,CueCreDelegate>{
CueCreateDelegate *cueCre;
}
MatrixViewController.m
CueCreatedCall is never called..
-(void)CueCreatedCall{
NSLog(#"lsakdlakjdlks");
}
- (void)viewDidLoad
{
cueCre = [[CueCreateDelegate alloc] init];
// [cueCre setdelegate:self];
[cueCre setDelegate:self];
NSLog(#"%#",[cueCre delegate]);
}