Array Objects update without assign - ios

I want to add image from Gallery/Camera to NSMutableDictionary & i am using following methods which i found Here
[dict setObject:UIImageJPEGRepresentation(chosenImage,0.5) forKey:#"image_four"];
[documents replaceObjectAtIndex:0 withObject:dict];
[tableOne reloadData];
In Cell for row at Indexpath
[cell.oneImgView setImage:[[UIImage alloc]initWithData:[dict objectForKey:#"image_four"]]];
I m adding NSMutableDictionary objects into one global array in ViewController A & Sending it to ViewController B where i add/update image from gallery/camera.
but when i press back button and go back UIViewController A and then again go to view controller B those images are still in that array.
In short, whenever i add image to Array of UIViewController B it some how affects to Array of UIViewController A.
I want this to be done on Done button click but if i click on back button of navigation bar it does the same as Done button.
- (IBAction)goToBack:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
Can someone tell me where i m going wrong?

Create another array and assign the ViewController array to this array
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
ViewControllerB *controllerb = [segue destinationViewController];
[controllerb setDocuments1:sender];
}
ViewControllerB.h
#property (nonatomic, strong) NSMutableArray *documents1;
ViewController.m
#import "ViewControllerB.h"
#import "UploadCell.h"
#interface ViewControllerB ()
{
NSArray *arrSavedObjects;
}
#end
#implementation ViewControllerB
#synthesize documents,documents1;
-(void)viewWillAppear:(BOOL)animated
{
arrSavedObjects = [[NSUserDefaults standardUserDefaults] objectForKey:#"arrayObjects"];
documents = [NSMutableArray arrayWithArray:arrSavedObjects];
if(documents.count==0)
{
documents = documents1;
}
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
//NSMutableDictionary *dict = [documents objectAtIndex:selected];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:[documents objectAtIndex:selected]];
if (![dict objectForKey:#"image1"]) {
[dict setObject:UIImageJPEGRepresentation(chosenImage, 0.5) forKey:#"image1"];
}
else{
[dict setObject:UIImageJPEGRepresentation(chosenImage, 0.5) forKey:#"image2"];
}
[documents removeAllObjects];
[documents addObject:dict];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:documents forKey:#"arrayObjects"];
[defaults synchronize];
[tableDocuments reloadData];
[controller dismissViewControllerAnimated:YES completion:nil];
}

Finally, solved by copying objects of NSObject class & adding it array.
[[controllerb setDocuments1]addObjectsFromArray:array];

Related

iOS objective c passing data between view controllers

I am new to iOS and I am not able to pass data from one controller to another. I am not able to access the variable in the second view controller
this is my method for passing I have created a delegate in .h file of receiving view controller
.h file of first view controller (sending)
#interface OtpViewController : UIViewController
#property (nonatomic,strong) NSString *str;
#property (strong,nonatomic) NSString *tmp;
#property(weak,nonatomic) NSString *requestReply ;
.m file of first view controller(sending)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender{
VerifyViewController *loadCtr = (VerifyViewController *)segue.destinationViewController;
loadCtr.delegate = self;
loadCtr.tmpStr = self.tmp;
NSLog(#"--%#",self.tmp);
[loadCtr setotp:self.tmpdict withMobile:_mobiletf.text];
//NSLog(#"otp:%#",[tmpdict valueForKey:#"otp"]);
NSLog(#"mobile:%#",_mobiletf.text);
}
.m file of second view controller(receiving)
-(void)setotp:(NSDictionary *)dic withMobile:(NSString *)str{
self.stri=[tmpdict valueforkey:#"otp"];
self.stri1=_mobiletf.text;
OtpViewController.[tmpdict valueforkey:#"otp"]=self.stri;
NSLog(#"%#----%#",self.stri,self.stri1);
}
.h file of second view controller(receiving)
#protocol VerifyViewControllerDelegate <NSObject>
#end
#interface VerifyViewController : UIViewController
#property (nonatomic,strong) NSString *otpStr;
#property(nonatomic,strong) NSString *mobileStr;
#end
actually I am trying to get otp from server and I have extracted the otp in the first view controller and now I have to pass otp and the mobile number from the text field to second view controller for verification of the otp please help!!
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; // this is json string
// NSError *error;
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; // you need to convert to dictionary object
NSLog(#"requestReply: %#", jsonDict);
self.tmp=[jsonDict valueForKey:#"otp"] ;
self.str=self.tmp;
NSLog(#"tmp storage inside block:%#",self.tmp);
}] resume];
[ self performSegueWithIdentifier:#"b1" sender:self];
NSLog(#" storage:%#",self.str);
NSLog(#"tmp storage:%#",self.tmp);
}
at log whatever is printed which is out of resume gives me null
this is my log data
2017-06-01 12:26:45.803 MenuBar[2652:124758] 9047038606
2017-06-01 12:26:45.809 MenuBar[2652:124758] storage:(null)
2017-06-01 12:26:45.810 MenuBar[2652:124758] tmp storage:(null)
2017-06-01 12:26:48.422 MenuBar[2652:124804] requestReply: {
otp = 325106;
success = 1;
}
2017-06-01 12:26:48.422 MenuBar[2652:124804] tmp storage inside block:325106
Use Below code:
#interface VerifyViewController : UIViewController
#property (nonatomic,strong) NSString *otpStr;
#property(nonatomic,strong) NSString *mobileStr;
Then pass values:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender
{
VerifyViewController *loadCtr = (VerifyViewController *)segue.destinationViewController;
loadCtr.otpStr = [tmpdict valueForKey:#"otp"];
loadCtr.mobileStr = _mobiletf.text;
}
You can access these 2 values in ViewDidLoad method of VerifyViewController.
self.otpStr and self. mobileStr
(As of Xcode Version 9.4.1 (9F2000) - iOS 11.4 - Objective C) 
Most will need to call several storyboard segue calls from a single UIViewController. Here is how to handle the different segue string identifiers within the preparForSegue delegate call.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString: #“CallerViewController_ToMusicPlayerViewController_Segue"])
{
MusicPlayerViewController * targetVC = (MusicPlayerViewController *)segue.destinationViewController;
targetVC.listName = #“Music Hits”;
}
if ([segue.identifier isEqualToString: #“CallerViewController_ToMusicListViewController_Segue"])
{
MusicListViewController * targetVC = (MusicListViewController *)segue.destinationViewController;
// if you need to manage a protocol delegate with caller VC
targetVC.savefolderChoiceDelegate = self;
}
}
The actual call to invoke the segue looks like:
-(void)buttonAction:(id)sender{
[self performSegueWithIdentifier:#“CallerViewController_ToMusicPlayerViewController_Segue" sender:sender];
}
Here is an example of Interface Builder Segue. the identifier is different, but imagine #“CallerViewController_ToMusicPlayerViewController_Segue" is actually #"ProtData_Add_Segue" in this image.

Change NSString value for ever : NSUserDefaults?

I have two views :
View1 (Shop) : URL stocked in NSString for displaying image.
View2 (ModifyShop) : Text field with URL from view1.
I can pass data from view1 to view2 : The URL stocked in NSString appears in Text field and pass data from view2 to view1. (URL for example)
Now I would like to modify this URL with Text field from view2 and that modify the NSString in view1 for ever. How can I make that ? Using NSUserDefaults ?
Here is my code :
Shop:
- (void)viewDidLoad {
[super viewDidLoad];
[self.modifyButton setHidden:YES];
}
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"admin"]) {
NSLog(#"pas admin");
} else {
[self.modifyButton setHidden:NO];
}
dispatch_async(dispatch_get_global_queue(0,0), ^{
self.imageButtonURL = #"http://bundoransurfshop.com/wp-content/uploads/2015/02/72-torq-pink.jpg";
imageButtonData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:self.imageButtonURL]];
if ( imageButtonData == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
self.imageButton.imageView.image = [UIImage imageWithData: imageButtonData];
});
});
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"modifyShop"]) {
ShopModify *viewcontroller = (ShopModify *)segue.destinationViewController;
viewcontroller.imageButtonURL = self.imageButtonURL; }
}
-(IBAction)prepareForUnwindShopModify:(UIStoryboardSegue *)segue {
NSLog(#"%#", self.imageButtonURL);
}
Shopmodify:
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.photoURL.text = [NSString stringWithFormat:#"%#", self.imageButtonURL];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
Shop *viewcontroller = (Shop *)segue.destinationViewController;
viewcontroller.imageButtonURL = self.photoURL.text;
}
You can store a URL string in NSUserDefaults by following this post:
Save string to the NSUserDefaults?
Simply have your view1 always get it from NSUserDefaults in viewWillAppear and have view2 change the NSUserDefaults key for the URL string and that should do it
If with foverer you mean even after you close and open again your app, replacing the default http://bundoransurfshop.com/wp-content/uploads/2015/02/72-torq-pink.jpg, yes, for example you could use NSUserDefaults (or any other persistent way to store your data/configuration).
Save on edit in view2:
[[NSUserDefaults standardUserDefaults] setObject:valueToSave
forKey:#"imageUrl"];
[[NSUserDefaults standardUserDefaults] synchronize]; //Important
Load/Reload in view1:
NSString *savedUrl = [[NSUserDefaults standardUserDefaults] stringForKey:#"imageUrl"];
if(!savedValue){
savedUrl = #"http://bundoransurfshop.com/wp-content/uploads/2015/02/72-torq-pink.jpg";
}
Official documentation for NSUserDefaults.

How to edit NSMutableArray in other Class

I have NSMutableArray in "AppDelegate.h"
#property (strong, nonatomic) NSMutableArray *myArray;
and "AppDelegate.m"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.myArray = [[NSMutableArray alloc] init];
return YES;
}
In UITableViewController i add objects in NSMutableArray
- (IBAction)AddComment:(UIBarButtonItem *)sender
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
SectionObject *sectionObject = [[SectionObject alloc] init];
sectionObject.id = (NSInteger*)appDelegate.myArray.count;
sectionObject.name = [NSString stringWithFormat:#"New object %i",appDelegate.myArray.count];
[appDelegate.myArray addObject:sectionObject];
[self.tableView reloadData];
}
To edit the object I pass other UITableViewController objects from the array controller
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navController = segue.destinationViewController;
ExerciseTableViewController *controller = (ExerciseTableViewController *)navController;
controller.contactdb = [appDelegate.myArray objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
}
When i am going back to write
-(void)viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
self.contactdb.name = self.nameTextField.text;
}
[super viewWillDisappear:animated];
}
I receive an error 'EXC_BAD_ACCESS'. If i not edit self.contactdb.name, I dont have error. How can i edit object in other controller?
Your if-statement:
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound)
basically guarantees your view controller has already been removed from the navigation stack. That's why you get a EXC_BAD_ACCESS error when trying to access properties from that view controller. You should place your self.contactdb.name = self.nameTextField.text statement somewhere else.

How do I send strings to another viewcontroller

I currently have a class and ViewController with a button action to get the username and password from a textfield and put them into their own NSString. I then use the NSString to perform a post request like so.
NSString *user = _username.text;
NSString *password = _password.text;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://thesite.com/login.php"]];
[httpClient setParameterEncoding:AFFormURLParameterEncoding];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:#"http://thesite.com/login.php"
parameters:#{#"username":user, #"password":password}];
AFHTTPRequestOperation * httpOperation = [httpClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
//success code
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//error handler
}];
[httpClient enqueueHTTPRequestOperation:httpOperation];
However I have another class and Viewcontroller to perform a get request. However, in order to perform this get request I need to get the "NSString *user" from the first View Controller. How would I go about doing this? Should I declare a NSString *user in the header of the first Viewcontroller and then in the second View controller declare an instance of the first class?
You can pass strings through viewcontrollers. Make therefore a segue between the two viewcontroller and named it for example "secondVC"
the when you want to switch to other view make this call
[self performSegueWithIdentifier:#"secondVC"];
and implement this method.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"secondVC"]) {
SecondViewController *second = (SecondViewController *)[segue destinationViewController];
second.userString = self.user;
}
}
You can use NSUserDefaults to store the username and use it in other ViewControllers.
For example, save it in your current ViewController.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:username forKey:#"UserName"];
[defaults synchronize];
get username it in another ViewController.
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *username = [defaults objectForKey:#"UserName"];
pass the userName to second view controller.
You can achieve it using following approaches.
try to pass the username when you are initialising your secondViewController like
SecondViewController * sVC = [SecondViewController alloc] initWithUserName: username];
for this in your SecondViewController class you have to modify the init method and add a property of userName {typeOF string}
#property (nonatomic, strong) NSString * userName
- (id) initWithUserName: (NSString *) name
{
self = [super initWithNibName: #"SecondViewController"
bundle: nil];
if (self)
{
self.userName = name;
}
return self;
}
Enjoy!!
Create object of first class in second class like this..
//First class
//Pass the values to seconClass
secondClass *appdelegate = [NSApp delegate];
[appdelegate initwithDetails:userName withPassword:password];
//Second class
//In second class declare the function and get the values
//When u create the object, init function will call first
-(id)initwithDetails:(NSString *)user withPassword:(NSString *)password
{
userName = [NSString stringWithFormat:#"%#", user];
newPass=[NSString stringWithFormat:#"%#", password];
return self;
}
If the second viewcontroller is spawned from the first you could just create a delegate protocol and corresponding delegate so that either the first is delegate of the second or the second is delegate of the first:
Here is an example of a protocol which includes one method, notice the instance variable delegate is of type id, as it will be unknown at compile time the type of class that will adopt this protocol.
#import <Foundation/Foundation.h>
#protocol ProcessDataDelegate <NSObject>
#required
- (void) processSuccessful: (BOOL)success;
#end
#interface ClassWithProtocol : NSObject
{
id <ProcessDataDelegate> delegate;
}
#property (retain) id delegate;
-(void)startSomeProcess;
#end
Inside the implementation section for the interface defined above we need to do two things at a minimum – first synthesize the delegate instance variable and second, call the method defined in the protocol as needed (more on that in a moment).
Let’s look at a bare bones implementation of the ClassWithProtocol.m:
#import "ClassWithProtocol.h"
#implementation ClassWithProtocol
#synthesize delegate;
- (void)processComplete
{
[[self delegate] processSuccessful:YES];
}
-(void)startSomeProcess
{
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:#selector(processComplete) userInfo:nil repeats:YES];
}
#end
Read more at this tutorial

TableView not showing new data loaded from plist after dismissing from other view

My First View is a UIViewController i have a UITable View in it and it works just fine.
From the first view i push another view, in that view i select a group name then the view dismiss, what i want is when i select the group name from the second view the first view loads the values of that group name to the table view, this is the code i use and its not working
the second view code
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
ViewController *theInstance = [[ViewController alloc] init];
[theInstance setGroupName:keyValue];
[theInstance ReceivedGroup:nil];
[self dismissViewControllerAnimated:YES completion:nil];
//tried that option and didnt work too, i added the rest of the code in the viewDidLoad
//[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:nil];
}
keyValue is NSString that been set on tableView didSelectRowAtIndexPath
the first view
- (IBAction)ReceivedGroup:(id)sender {
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:groupName];
nameArray = [[NSMutableArray alloc] init];
[nameArray addObjectsFromArray:tempArray];
[nameTable reloadData];
NSLog(#"Group Name : %#",groupName);
NSLog(#"Array : %#",nameArray);
}
groupName is NSString
In the log i get the groupName and the nameArray printed
but the tableView is empty.
EDIT: I fixed the problem and posted my answer
Your viewcontroller "theInstance" will be deallocated immediately after calling sendNames: so nothing's gonna happen. You should rather pass a pointer of your first viewcontroller to your second viewcontroller (e.g. set it as a property) and perform all operations on this viewcontroller.
subclass UITableViewController
#interface SecondViewController : UITableViewController
#property (nonatomic, strong) ViewController *firstViewController;
#end
if using storyboard segues implement in your first viewcontroller :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
((SecondViewController *) segue.destinationViewController).firstViewController = self;
}
sendNames: should then look like this:
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
ViewController *theInstance = self.firstViewController;
[theInstance setGroupName:keyValue];
[theInstance ReceivedGroup:nil];
[self dismissViewControllerAnimated:YES completion:nil];
//tried that option and didnt work too, i added the rest of the code in the viewDidLoad
//[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:nil];
}
I Fixed it by sending the keyValue using NSNotificationCenter
Here is my code now
For The Second View
- (IBAction)sendNames:(id)sender {
if (!keyValue) {
NSLog(#"Didnt Select Any Group To Send");
return;
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"RG" object:keyValue];
[self dismissViewControllerAnimated:YES completion:nil];
}
Then On The First View
- (void)receiveNotification:(NSNotification *)notification {
NSString *Key = [notification object];
nameArray = [[NSMutableArray alloc] init];
[nameArray removeAllObjects];
NSString *path = [self dataFilePath];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray *tempArray = [dict objectForKey:Key];
[nameArray addObjectsFromArray:tempArray];
[self.nameTable reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[nameTable numberOfRowsInSection:0] - 1 inSection:0];
[nameTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receiveNotification:) name:#"RG" object:nil];
}

Resources