how to implement uisearchcontroller for complete app - ios

I know how to implement UISearchController for a table view. But can anyone help me in implementing search bar for complete app.
In my app i have 3 view controllers
a)students VC
b)teachers VC
c)parents VC
and I have a search button. Here i want to implement complete in app search functionality. If we type in a name it should appear in a table view either it is in students/parents/teachers. I am not getting any idea how to start this. Please give some KT.

I just try to create singleton class that store value and use as a global. So first you need to create a Singleton-class using following code:
#import <Foundation/Foundation.h>
#interface GlobalData : NSObject
{
NSMutableArray *ClassArray;
}
+(GlobalData *) getInstance;
-(void)saveClassARray:(NSArray *)array;
-(NSMutableArray *)getGlobalArray;
#end
It's .M Class
#import "GlobalData.h"
#implementation GlobalData
static GlobalData *instanceGlobalData;
+(GlobalData *) getInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instanceGlobalData = [[GlobalData alloc] init];
instanceGlobalData->ClassArray = [[NSMutableArray alloc]init];;
});
return instanceGlobalData;
}
-(void)saveClassARray:(NSArray *)array
{
[ClassArray addObjectsFromArray:array];
}
-(NSMutableArray *)getGlobalArray
{
return ClassArray;
}
#end
Now you need to store your Students, Teachers and Parents data by following code.
First you need to import #import "GlobalData.h" in your ViewController and create define variable that like following:
#import "GlobalData.h"
#define USERDATASINGLETON (GlobalData *)[GlobalData getInstance]
And in Web services Call back Success you need to store your data in globle array using following code:
NSArray *array =[[NSArray alloc]initWithObjects:#"Nitin",#"Nit", nil];
[USERDATASINGLETON saveClassARray:array];
Above array is just for your referance do same things for all your 3 ViewController and store the result using saveClassARray. now finally you need to get full array by following code:
NSMutableArray *FinalGlobalArray = [USERDATASINGLETON getGlobalArray];
NSLog(#"==%#",FinalGlobalArray);
That will be NSlog allof the data that have you stored. but make sure use some check that once you add teacher,student,parents data and if saveClassARray calling again that old data wont be overtire that will be create duplicate entry so take care about.
Now you have finalArray you can do your search code that you have did for individual.
Hope that help

Related

How to use NSMutableArray from Master Controller in Detail Controller

I am using UISplitViewController and I have a Master Controller and Detail Controller.
The Master Controller I have a NSMutableArray defined like so:
#import "MasterController.h"
#import "DetailController.h"
#interface MasterController ()
#property NSMutableArray *objects;
#end
#implementation MasterController
and I am trying to call it in my Detail Controller like so:
#import "DetailController.h"
#import "MasterController.h"
#interface DetailController ()
{
MasterController *purchaseOrder;
}
#end
#implementation DetailController
- (void)GetRequest
{
NSArray *tableData = [dataSource.areaData GetPurchaseOrderItems:[NSString stringWithFormat:#"%#%#",areaPickerSelectionString,unitPickerSelectionString]];
NSLog(#"%#", tableData);
//TODO: foreach tableData populate object.
[purchaseOrder object];
}
ultimately I am looking to populate the object with each item in tableData. But when I call object, I get this error:
No visible #interface for 'LHPurchaseOrderMaster' declares the selector 'object'
how would I accomplish what I am trying to accomplish ?
So many things amiss here. A few short pointers to hopefully help:
You've put #property NSMutableArray *objects; in your private interface. Try moving this to the header file and making it public. Any reason why you haven't declared this as #property (nonatomic, strong) NSMutableArray *objects; ?
The syntax [someInstance someMethod] means that your purchaseOrder instance of MasterController is trying to call a method called object of which you've not provided us any details about. Perhaps you're trying to call objects instead. But this will only work if you make it public as noted above.
If you're attempting to design a better API than that, you can keep your NSMutableArray of objects private, and provide a public NSArray of maybe *allObjects and inside yourDetailController a getter method like
- (NSArray*)allObjects {
return [self.objects copy];
}
You've not provided any information about LHPurchaseOrderMaster, but hopefully I'm on the right track with helping you solve your problem here.

How to access global Array without using AppDelegate in ios

I have implemented Opencv in one of my project. In an opencv .mm file, I need to access the appdelegate object for global access of an array but it is giving Linker Error all the time (When I am trying to import the AppDelegate Class). So I have created an NSObject Class, still I can not access the Global Array which is created as the #property of the NSObject (I have imported the NSObject class in the .mm file). Array is giving the NULL value.
So where do I create the Array by which I can access the array in my whole project?
I can not use the NSUSerDefaults and DocumentDirectory. Because I want to save a lots of images and video links in that array, So I can not use NSUserDefaults and I don't want to use again the phone memory for the temp file as because I am picking the images from the Photolibrary, so DocumentDirectory is discarded, So Is there any way by which I can create the global array and access them from the openCV files i.e objective CPP files?
you can make class as UserdataSingleton which overrides NSObject. which you can use all over your application to share data globally (for your case array). this code template may help you:
#import <Foundation/Foundation.h>
#interface UserDataSingleton : NSObject
{
#private
NSArray *globalArray;
}
+(UserDataSingleton *) getInstance;
-(void)saveInUserDatasingletonWithArray:(NSArray *)array;
-(NSDictionary *)getGlobalArray;
#end
and implementation file will be some thing like:
#import "UserDataSingleton.h"
#implementation UserDataSingleton
static UserDataSingleton *userDataSingletonInstance;
+(UserDataSingleton *) getInstance
{
if (userDataSingletonInstance == nil) {
userDataSingletonInstance = [[UserDataSingleton alloc] init];
}
return userDataSingletonInstance;
}
-(void)saveInUserDatasingletonWithArray:(NSArray *)array
{
globalArray = array;
}
-(NSDictionary *)getGlobalDictionary
{
return globalArray;
}
#end
================== usage:
#import "UserDataSingleton.h"
#define USERDATASINGLETON (UserDataSingleton *)[UserDataSingleton getInstance]
......................your code...
NSArray *this_IS_Array_Populated_here_For_Global_Access = [NSArray alloc] initWith....];
[USERDATASINGLETON saveInUserDatasingletonWithArray:this_IS_Array_Populated_here_For_Global_Access];//you put your array for global access.
later some where in any other view or view controller you can get that global array for example lets say you have YourViewController class:
NSMutableArray *yourArrayFromWebResponse = [USERDATASINGLETON getGlobalArray];
thanks
Note that Objective C is a superset of C. Thus, you can have regular C variables in your program. My favorite is to make a global variable for my appDelegate. Put this in your app delegate's .h file:
MyAppDelegateClass * appDelegate;
(change "MyAppDelegateClass" to your appDelegate's class name) and put this in application: didFinishLaunchingWithOption: method in your app delegate's .m file:
appDelegate = self; // set universal global variable
Now just #import your app delegate's .h file and have access to your appDelegate from anywhere.
You may try to create a singleton objet like and access it from everywhere
you could define a macro in your delegate like so:
#define sharedAppDelegate ((AppDelegate *)[UIApplication sharedApplication].delegate)
and then in the class which you want to access your array import your AppDelegate class, boiler plate would be:
#import AppDelegate.h
and then just use:
NSArray *arrayYouWanted = [AppDelegate sharedAppDelegate].yourPropertyArrayName;
You can also store it in NSUserDefaults if you want to persist it.

I need to make one instance of an array that can be access by multiple view controllers [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 9 years ago.
I need to make one instance of an array that can be access by multiple view controllers. It will contain objects that will be displayed in a table view and created by a modular view and then displayed in the table view. I can't figure out how to access it once I make a #property for it in the main view controller or the AppDelegate class.
You should make a singleton and the recommended way to do that in objective-c is to create a class and add a method that looks something like:
+ (YourClass *)sharedYourClass
{
static dispatch_once_t onceToken;
static YourClass *sharedInstance;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
Put the array as a property in your class.
//YourClass.h
#interface YourClass : NSObject
#property(nonatomic, strong)NSArray *yourArray;
+(YourClass *)sharedYourClass;
#end
And in every class you want to use your singleton start by importing YourClass.h and then use it like:
NSArray *arr = [YourClass sharedYourClass].yourArray;
[YourArray sharedYourClass].yourArray = [[NSArray alloc] init];
etc..
What I do is put the data I want shared, in your instance the array, in the AppDelegate. Then I define a protocol that the app delegate conforms to. This lets me access the data anywhere. For example, say I have an array I want everywhere:
First define a protocol:
#protocol ApplicationState<NSObject>
#property(nonatomic, strong) NSArray* data;
#end
Then make your app delegate conform to it:
#interface AppDelegate : UIResponder <UIApplicationDelegate, ApplicationState>
#property (strong, nonatomic) UIWindow *window;
#property(nonatomic, strong) NSArray* data;
#end
Then reading and writing this shared object is simple:
id<ApplicationState> appState = (id<ApplicationState>) [UIApplication sharedApplication].delegate;
appState.data = [[NSArray alloc] init];
I am going to assume you can make the class of the array inherit from NSObject, and then pass it to the View Controller from there...
You have 2 ways to do this:
1.- Instantiate 1 arra on the main class and pass the reference to each viewcontroller what you need.
2.- Make a singleton class to hold the array an use this in your project.
First create a class like this
//GlobalDataClass.h
#interface GlobalDataClass : NSObject
#property(nonatomic,retain)NSArray *myArray;
+(GlobalDataClass*)getInstance;
#end
#import "GlobalDataClass.h"
//GlobalDataClass.m
#implementation GlobalDataClass
#synthesize myArray;
static GlobalDataClass *instance =nil;
+(GlobalDataClass *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance = [GlobalDataClass new];
}
}
return instance;
}
#end
Then you can use it in your viewControllers like this:
-(void)viewDidLoad{
[super viewDidLoad];
self.dataObj = [GlobalDataClass getInstance];
NSLog(#"%#",self.dataObj.myArray);
}
Hope it helps!

How to use an internal method in a Objective-C category?

Trying to extend the capabilities from a open source project, I wrote a category for add a new method. In this new method, the category needs to access to an internal method from the original class, but the compiler says that it can't find the method (of course, is internal). Is there any way to expose this method for the category?
EDIT
I don't want to modify the original code, so I don't want to declare the internal method in the original class header file.
The code
In the original class implementation file (.m), I have this method implementation:
+(NSDictionary*) storeKitItems
{
return [NSDictionary dictionaryWithContentsOfFile:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
#"MKStoreKitConfigs.plist"]];
}
In the category, I want to add this method:
- (void)requestProductData:(NSArray *(^)())loadIdentifierBlock
{
NSMutableArray *productsArray = [NSMutableArray array];
NSArray *consumables = [[[MKStoreManager storeKitItems] objectForKey:#"Consumables"] allKeys];
NSArray *nonConsumables = [[MKStoreManager storeKitItems] objectForKey:#"Non-Consumables"];
NSArray *subscriptions = [[[MKStoreManager storeKitItems] objectForKey:#"Subscriptions"] allKeys];
if(loadIdentifierBlock != nil) [productsArray addObjectsFromArray:loadIdentifierBlock()];
[productsArray addObjectsFromArray:consumables];
[productsArray addObjectsFromArray:nonConsumables];
[productsArray addObjectsFromArray:subscriptions];
self.productsRequest.delegate = self;
[self.productsRequest start];
}
In every line in which I call storeKitItemscompiler says: Class method "+storeKitItems" not found ...
This is trivial, make a forward declaration of the method.
Unfortunately, in obj-c, every method declaration must be inside #interface, so you can make it work in your category .m file with another internal category, e.g.
#interface MKStoreManager (CategoryInternal)
+ (NSDictionary*)storeKitItems;
#end
No implementation is needed, this only tells the compiler the method is somewhere else, similarly to #dynamic with properties.
If you are only interested in removing the warning, you can also just cast the class to id, the following should work, too:
NSDictionary* dictionary = [(id) [MKStoreManager class] storeKitItems];
However, my favorite solution is to do it a bit differently, let's assume the following example:
#interface MyClass
#end
#implementation MyClass
-(void)internalMethod {
}
#end
#interface MyClass (SomeFunctionality)
#end
#implementation MyClass (SomeFunctionality)
-(void)someMethod {
//WARNING HERE!
[self internalMethod];
}
#end
My solution is to split the class into two parts:
#interface MyClass
#end
#implementation MyClass
#end
#interface MyClass (Internal)
-(void)internalMethod;
#end
#implementation MyClass (Internal)
-(void)internalMethod {
}
#end
And include MyClass+Internal.h from both MyClass.m and MyClass+SomeFunctionality.m
A category has no access to the private methods of a class. It's no different than trying to call those methods from any other class. At least if you call the private method directly. Since Objective-C is so dynamic, you can call private methods (which is a bad idea) using other means such as using performSelector or with NSInvocation.
Again, this is a bad idea. An update to the implementation of the class could break your category.
Edit: Now that there is code posted -
Since the +storeKitItems method is not declared in the .h file, no category or other class can access the private method.
In you category implementation file you can define and informal protocol for the method
#interface YourClasses (ExternalMethods)
+(NSDictionary*) storeKitItems;
#end
This will stop the compiler from complaining about not knowing of the method storeKitItems in you category.

object sharing among view controllers

I was wondering how can I share a NSDictionary objects among several view controllers which basically are tabs in my application.
I tried using a protocol, like in Java, so that I can cast to the protocol and access the property. That doesn't seem to work.
Also I had a look at similar question at
How to share data globally among multiple view controllers
But I observed that the appDelegate method is not safe and may lead to memory leak.
Similarly injection on class A into class B will create the same problem.
So can anyone suggest me any method which i should study or implement in my code?
If you wants to share only Dictionary, why don't you go for class method using from helper class.
+(NSDictionary *)shareMethod
{
return dict;
}
You can use singleton class for sharing the data
Check this Singleton class
MyManger.h
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSMutableDictionary *_dict
}
#property (nonatomic, retain) NSMutableDictionary *dict;
+ (id)sharedManager;
#end
MyManger.m
#import "MyManager.h"
static MyManager *sharedMyManager = nil;
#implementation MyManager
#synthesize dict = _dict;
#pragma mark Singleton Methods
+ (id)sharedManager {
#synchronized(self) {
if(sharedMyManager == nil)
sharedMyManager = [[super allocWithZone:NULL] init];
}
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
dict = [[NSMutableDictionary alloc] init];
}
return self;
}
You can access your dictionary from everywhere like this
[MyManager sharedManager].dict
I found a way out. Since I want a dictionary to be shared across, I declared a method in my protocol
- (void) setSingleHouse:(NSDictionary*) singleHouse;
In each of my controller I implemented the method in a appropriate manner. Hence I was able to share across them for now.
Also I figured out that I was casting in a wrong way earlier i.e (#protocol(protocol name)). Now changed it into NSObject .
Sorry for the fuss.
I advise you not to use a property in your appDelegate instance. This pattern doesn't improve code reusability.
Basicly your shared NSDictionnary is your model. So, if you want your code to follow the MVC design parttern, you should create a class with a shared instance that would contain your NDDictionnary in a public property.
This is well explained in this post
This way, you will access your shared NSDictionnary this way
:
NSDictionary* sharedDictionnary = [MyModel sharedInstance].sharedDictionary;

Resources