access objects from Bluetooth manager using singleton in ios - ios

I am trying to create a singleton class for my BLEManager which gets called on viewdidload of the launch screen ViewController. How can I get the objects _transporter and _BLEAdapter in my view controller after the init is completed?
BLEManager.h
#interface MyManager : NSObject {
BLETransporter* _transporter;
BLEAdapter* _BLEAdapter;
}
#property (strong, nonatomic) BLETransporter* transporter;
#property (strong, nonatomic) BLEAdapter* BLEAdapter;
+ (id)sharedInstance;
#end
BLEManager.m
#implementation MyManager
#synthesize BLEAdapter=_BLEAdapter;
#synthesize transporter = _BLEAdapter;
+(BLEManager*)sharedInstance{
static BLEManager *sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (id)init {
if (self = [super init]) {
_transporter = [BLETransporter transporterWithIdentifier:nil serviceUUIDs:serviceUUIDs];
[_transporter connectWithBlock:^(NSInputStream * _Nullable inputStream, NSOutputStream * _Nullable outputStream) {
if ( !inputStream )
{
LOG( #"Could not connect to device" );
return;
}
_BLEAdapter = [BLEAdapter adapterWithInputStream:inputStream outputStream:outputStream];
[_BLEAdapter connect];
}];
}
return self
}

Related

Make one method in view controller globally and call it to many view controllers

I want to make one single method and call it, to many view controllers. Help me? and i also want to alloc UIView or button or label on that Fixed View.
HERE IS MY CODE
.h
#import <UIKit/UIKit.h>
#interface UIOnlyView : UIView
+ (UIOnlyView *) sharedGlobalClass;
-(void)yourMethod;
#end
.m
+(UIOnlyView *)sharedGlobalClass {
static dispatch_once_t pred;
static id shared = nil;
dispatch_once(&pred, ^{
shared = [[super alloc] init];
});
return shared;
}
-(void)yourMethod{
NSLog(#"Method called");
UIView *customView=[[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
customView.backgroundColor=[UIColor redColor];
[self addSubview:customView];
}
But my Custom view is not show on my view controller class where i called this method.
Use a singleton like this
create a class for example GlobalClass with type NSObject
In .h class create this method
+ (GlobalClass *) sharedGlobalClass;
- (void) yourMethod : (UIView *) view;
Now in .m class
+ (GlobalClass *) sharedGlobalClass {
static dispatch_once_t pred;
static id shared = nil;
dispatch_once(&pred, ^{
shared = [[super alloc] init];
});
return shared;
}
- (void) yourMethod : (UIView *) view {
UIView *customView=[[UIView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
customView.backgroundColor=[UIColor redColor];
[view addSubview:customView];
}
Now you can call this method like this
[[GlobalClass sharedGlobalClass] yourMethod:self.view];
from any of your ViewController, you just have to import
#import "GlobalClass.h"
In Objective C:
#interface OUCSCalendarManager ()
- (void)globalMethod;
#end
#implementation OUCSCSharedManager
/// ------------------------------------------------------------------------
/// Singleton Method
///--------------------------------------------------------------------------
+(instancetype)SharedManager{
#synchronized(self) {
static OUCSCalendarManager *sharedInstance = nil;
static dispatch_once_t pred;
#synchronized (self) {
dispatch_once(&pred, ^{
sharedInstance = [[OUCSCalendarManager alloc]init];
});
return sharedInstance;
}
}
}
- (void)globalMethod {
}
}
To Call That method from anywhere in project you need to create the singleton object and call method like this
[[OUCSCalendarManager calendarSharedManager]globalMethod];
Let me know if you face any issue.
ClassA.h
#import "ClassA.h"
#interface ClassA : NSObject
+(id)sharedInstance;
-(void)customMethod;
#end
Now Implementation of ClassA.m
#import "ClassA.h"
#implementation ClassA
+(id)sharedInstance
{
static ClassA *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[ClassA alloc] init];
});
return instance;
}
-(void)customMethod
{
//Method body
}
Now import the header file in other viewcontrollers and use it like
[[ClassA sharedInstance] customMethod{}];
You can use the singleton class for this purpose:
create a NSObject class:
import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSString *someProperty;
}
#property (nonatomic, retain) NSString *someProperty;
+ (id)sharedManager;
#end
In your .m file:
import "MyManager.h"
#implementation MyManager
#synthesize someProperty;
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
you can use the someProperty globally in all class.
it defines a static variable initialised once and only once in sharedManager.
for more info: http://www.galloway.me.uk/tutorials/singleton-classes/
https://code.tutsplus.com/articles/design-patterns-singletons--cms-23886

Objective-C Defining a Global Array for use by several ViewControllers

I've been trying to implement a global NSMutableArray from what I think to be a singleton class that I've implemented.
I can enter ViewController # 2, add and remove objects to the array.
However, when I leave ViewController #2 and come back, the data does not persist, and I have an array with 0 objects.
What do you think I'm doing wrong?
.h
// GlobalArray.h
#interface GlobalArray : NSObject{
NSMutableArray* globalArray;
}
+(void)initialize;
.m
#import "GlobalArray.h"
#implementation GlobalArray
static GlobalArray* sharedGlobalArray;
NSMutableArray* globalArray;
+(void)initialize{
static BOOL initalized = NO;
if(!initalized){
initalized = YES;
sharedGlobalArray = [[GlobalArray alloc] init];
}
}
- (id)init{
if (self = [super init]) {
if (!globalArray) {
globalArray = [[NSMutableArray alloc] init];
}
}
return self;
}
View Controller #2
GlobalArray* myGlobalArray;
myGlobalArray = [[GlobalArray alloc] init];
//Various add and remove code
Thank you for your input.
Following is best approach to share data Globally at Application level. Singleton Class is a key. Singleton is only initialised once, rest of times shared data is returned.
#interface Singleton : NSObject
#property (nonatomic, retain) NSMutableArray * globalArray;
+(Singleton*)singleton;
#end
#implementation Singleton
#synthesize globalArray;
+(Singleton *)singleton {
static dispatch_once_t pred;
static Singleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[Singleton alloc] init];
shared.globalArray = [[NSMutableArray alloc]init];
});
return shared;
}
#end
Following is the way to access/use shared data.
NSMutableArray * sharedData = [Singleton singleton].globalArray;
You create separate instance of GlobalArray in your ViewController#2 with this code:
GlobalArray* myGlobalArray;
myGlobalArray = [[GlobalArray alloc] init];
Instead, you should create accessor method to return your shared instance, something like this:
// GlobalArray.h
#interface GlobalArray : NSObject{
NSMutableArray* globalArray;
}
+(void)initialize;
+(GlobalArray*)sharedInstance;
with implementation:
// GlobalArray.m
// ... your existing code
// accessor method
+(GlobalArray*)sharedInstance
{
return sharedGlobalArray;
}
and then call it from your ViewController#2:
GlobalArray* myGlobalArray = [GlobalArray sharedInstance];
However, using global variables to transfer data between view controllers is bad practice; I suggest you to use more safe methods, create a delegate, for example.
To create a shared global array, if that's really what you want, just put this in the header file:
extern NSMutableArray *myGlobalArray;
and this in your main source file:
NSMutableArray *myGlobalArray;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myGlobalArray = [NSMutableArray new];
}
Use this code for set and get the array views, for adding and removing do it separate in controller itself.
// GlobalArray.h
#interface GlobalArray : NSObject
#property (nonatomic, strong) NSMutableArray* globalArray;
+ (id)sharedManager;
-(NSMutableArray *) getGlobalArray;
-(void) setGlobalArray:(NSMutableArray *)array;
#end
/*-----------------------------------------*/
#import "GlobalArray.h"
#implementation GlobalArray
+ (id)sharedManager {
static GlobalArray *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init{
if (self = [super init]) {
if (!globalArray) {
globalArray = [[NSMutableArray alloc] init];
}
}
return self;
}
-(NSMutableArray *) getGlobalArray{
return self.globalArray;
}
-(void) setGlobalArray:(NSMutableArray *)array{
_globalArray = globalArray;
}
#end
-------------------------
//get array
NSArray * array = [[GlobalArray sharedManager] getGlobalArray];
//set array
[[GlobalArray sharedManager] setGlobalArray:array]
-------------------------

How to call Objective-C instancetype method in Swift?

I have an Objective-C class which looks like this:
#interface CustomObjectHavingData : NSObject
#property (nonatomic, strong) NSData *objWithData;
- (instancetype)initWithObjHavingData;
#end
and implementation like this
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData{
if (self = [super init]) {
NSString *str = #"This is simple string.";
self.objWithData = [str dataUsingEncoding:NSUTF8StringEncoding];
}
return self;
}
#end
Now I want to call this initWithObjHavingData in Swift
var objData = CustomObjectHavingData()
This returns nil to me. Please help how I can call the above init method here.
You are not supposed to write initializer like that in Objective C. Either you should have it just init or then if you are passing argument in constructor then only you can name it otherwise.
Here is how you can do it,
#interface CustomObjectHavingData : NSObject
#property (nonatomic, strong) NSData *objWithData;
- (instancetype)initWithObjHavingData:(NSData *)data;
#end
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData:(NSData *)data
{
if (self = [super init]) {
_objWithData = data;
}
return self;
}
#end
In Swift, you can simply call it like this,
let myCustomObject = CustomObjectHavingData(objHavingData: someData)
The name is quite inappropriate though.
If you want to call the init method without any parameter with the requirements I posted in the question, we have to write the init method like this:
#interface CustomObjectHavingData : NSObject
#property (nonatomic, strong) NSData *objWithData;
- (id)init;
#end
And implement it like this
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData{
if (self = [super init]) {
NSString *str = #"This is simple string.";
self.objWithData = [str dataUsingEncoding:NSUTF8StringEncoding];
}
return self;
}
#end
#implementation CustomObjectHavingData
- (instancetype)initWithObjHavingData:(NSData *)data
{
if (self = [super init]) {
_objWithData = data;
}
return self;
}
#end
Then, you can call this from swift like this:
var objData = CustomObjectHavingData()
It will by default initialize all the objects.
You can use this :
+ (Common *)sharedInstance
{
static Common *sharedInstance_ = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
sharedInstance_ = [[Common alloc] init];
});
return sharedInstance_;
}
After that for calling
var com_obj : Common!
com_obj = Common.sharedInstance()
com_obj.anyfunc(..)

NSCache is returning null after restarting project

I'm working with NSCache in Objective-C and Cocoa for iOS. Every time I restart the project, the getCacheRecommend call returns null and I expect it to return a value.
#import <Foundation/Foundation.h>
#class ASJsonDiscoverModel;
#interface ASUserCache : NSObject
+ (ASUserCache *)sharedInstance;
- (void)clear;
- (void)setCacheRecommend:(ASJsonDiscoverModel *)discover;
- (ASJsonDiscoverModel *)getCacheRecommend;
ASJsonDiscoverModel is my custom object class.
#import "ASUserCache.h"
#interface ASUserCache ()
#property (nonatomic,strong) NSCache *cache;
#end
#implementation ASUserCache
+ (ASUserCache *)sharedInstance
{
__strong static ASUserCache *cache = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cache = [[ASUserCache alloc] init];
});
return cache;
}
- (instancetype)init
{
if (self = [super init]) {
_cache = [[NSCache alloc] init];
}
return self;
}
- (void)setCacheRecommend:(ASJsonDiscoverModel *)discover
{
NSString *key = #"channelRecommend";
[_cache removeObjectForKey:key];
[_cache setObject:discover forKey:key];
}
- (ASJsonDiscoverModel *)getCacheRecommend
{
NSString *key = #"channelRecommend";
return [_cache objectForKey:key];
}
- (void)clear
{
if (_cache) {
[_cache removeAllObjects];
}
}
- (NSString *)keyforUserID:(NSString *)userID
{
return [NSString stringWithFormat:#"**%#",userID];
}

How to keep a variable in memory until the app quits

I have a singleton object in iOS that when instantiated parses a CSV file and then holds the results. I would like to make this object universally accessible and I would like it to not be released from memory until the app quits. I am running ARC so I cannot do manual retains.
Is there a way I can do this so it will work with ARC?
Header File:
#import <Foundation/Foundation.h>
#import "CHCSV.h"
#import "RCParserObject.h"
#interface ParserStore : NSObject <CHCSVParserDelegate>
{
// CSV Variables
RCParserObject *item;
NSMutableArray *data;
NSMutableArray *parsedData;
int fields;
bool open;
}
#property (atomic, retain) RCParserObject *item;
#property (atomic, retain) NSMutableArray *data;
#property (atomic, retain) NSMutableArray *parsedData;
#property (atomic) int fields;
#property (atomic) bool open;
+ (ParserStore *) defaultStore;
- (void) parseCSVFile:(NSString*)file;
- (void) categorizeData;
Implementation File
#import "ParserStore.h"
#import "RCParserObject.h"
#import "RCDetailItem.h"
static ParserStore *defaultStore;
#implementation ParserStore
#synthesize item, data, parsedData, fields, open;
# pragma mark -
# pragma mark Singleton Methods
+ (ParserStore *) defaultStore
{
if (!defaultStore)
{
defaultStore = [[super allocWithZone:NULL] init];
}
return defaultStore;
}
+ (id) allocWithZone:(NSZone *)zone
{
return [self defaultStore];
}
- (id) init
{
NSLog(#"Running init on parser store");
if (defaultStore)
{
NSLog(#"Self data count is %d, right before return", self.parsedData.count);
return defaultStore;
}
// NSLog(#"This better only happen once");
self = [super init];
[self setParsedData:[[NSMutableArray alloc] init]];
[self parseCSVFile:#"ContentNoPathFileExt2ASCII"];
[self categorizeData];
// NSLog(#"Self data count is %d when first created", self.parsedData.count);
return self;
}
#property (atomic, retain) RCParserObject *item;
#property (atomic, retain) NSMutableArray *data;
#property (atomic, retain) NSMutableArray *parsedData;
#property (atomic) int fields;
#property (atomic) bool open;
+ (ParserStore *) defaultStore;
- (void) parseCSVFile:(NSString*)file;
- (void) categorizeData;
#end
+(MySingleton *)singleton {
static dispatch_once_t pred;
static MySingleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingleton alloc] init];
shared.someVar = someValue; // if you want to initialize an ivar
});
return shared;
}
From anywhere:
NSLog(#"%#",[MySingleton singleton].someVar);
Note that your iOS app already has a singleton that you can access anywhere:
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
a simple singleton would be something like... in the .h:
#interface Foo : NSObject
+ (Foo *)sharedInstance;
#end
and in the .m:
static Foo *_foo = nil;
#implementation Foo
+ (Foo *)sharedInstance {
if (!_foo)
_foo = [[Foo alloc] init];
return _foo;
}
#end

Resources