In a simple test app for iPhone I display (using SDWebImage) a user avatar on the top:
When the app user taps the avatar I'd like to display that picture "fullscreen" in another view.
So I have added that view to my Xcode 5 storyboard and also tap recognizer and the push segue which I've called "pushZoom" (here fullscreen):
The tap recognizer works okay, I can see its method being called.
My question: is there maybe a simple way in Interface Builder to pass the image to the new view or do I have to go the tedious way (add ZoomViewContoller.[mh] files, define an outlet for the image view there)?
Below is the copy of my ViewController.m in case I modify it later # GitHub:
#import "ViewController.h"
#import <SDWebImage/UIImageView+WebCache.h>
static NSString* const kAppleMaps = #"https://maps.apple.com/?q=%#";
static NSString* const kGoogleMaps = #"comgooglemaps-x-callback://?q=%#&x-success=myphone://?resume=true&x-source=MyPhone";
static NSString* const kAvatar = #"https://lh6.googleusercontent.com/-6Uce9r3S9D8/AAAAAAAAAAI/AAAAAAAAC5I/ZZo0yzCajig/photo.jpg";
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setTitle:#"Google+"];
_firstName.text = #"Alex";
[_cityBtn setTitle:#"Bochum" forState:UIControlStateNormal];
[_imageView setImageWithURL:[NSURL URLWithString:kAvatar]
placeholderImage:[UIImage imageNamed:#"Male.png"]];
}
- (IBAction)avatarTapped:(id)sender {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
- (IBAction)cityPressed:(id)sender
{
NSURL* testURL = [NSURL URLWithString:#"comgooglemaps-x-callback://"];
NSString* fmt = ([[UIApplication sharedApplication] canOpenURL:testURL] ? kGoogleMaps : kAppleMaps);
NSString* city = [self urlencode:_cityBtn.currentTitle];
NSString* str = [NSString stringWithFormat:fmt, city];
NSLog(#"%s: city=%# str=%#", __PRETTY_FUNCTION__, city, str);
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];
}
- (NSString*)urlencode:(NSString*)str
{
return (NSString*)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) str,
NULL,
CFSTR(":/?#!$&'()*+,;="),
kCFStringEncodingUTF8));
}
#end
Why do you need another viewController. You may keep an imageView of full size over you view without any image initially and keep it hidden, and on tapping that button, remove it from hiding. and just pass the image. So it doesn't need any of these problems. It seems simple for me
In my experience is small , but I show my idea
- (IBAction)avatarTapped:(id)sender {
//here use your choice in singleton or NSUserdefaults for passing the image url from one VC to another VC. here I used NSUserdefaults
[[NSUserDefaults standardUserDefaults]setObject:kAvatar forKey:#"userimage"];
}
in your full image show ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *userimg =[[NSUserDefaults standardUserDefaults]stringForKey:#"userimage"];
[_imageView setImageWithURL:[NSURL URLWithString:userimg]
placeholderImage:[UIImage imageNamed:#"Male.png"]];
}
Pass image URL as string or url to next screen and show it in an imageView using
[self.myImageView setImageWithURL:[NSURL URLWithString:photoURL] placeholderImage:[UIImage imageNamed:#"loading.png"]];
Thats what i would do.Please post here if you got some better idea.
Related
I have a code (objective-c) that should open a new window (viewcontroller) when a link with a certain string in a uiwebview is clicked. But it doesn't work.
Here's the code from the .m file:
-(BOOL)webView2:(UIWebView*)webView2 shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
//Check if special link
if ( [ urlString isEqualToString: #"http://google.com/" ] ) {
//Here present the new view controller
ViewController *ViewController8 = [[ViewController alloc] init];
[self presentViewController:ViewController8 animated:YES completion:nil];
return NO;
}
return YES;
}
The new viewcontroller subclass name is: ViewController8 and the UIWebView subclass is: webView2
Here's the code from the .h file:
#import <UIKit/UIKit.h>
#interface ViewController8 : UIViewController
#end
#interface ViewController : UIViewController{
IBOutlet UIScrollView *scrollView;
IBOutlet UIButton *openMenu;
int draw1;
}
- (IBAction)OpenMenu:(id)sender;
#property (retain, nonatomic) IBOutlet UIScrollView *scrollView;
#end
How do I fix it so a new window (viewcontroller) is opened when a link with a certain string in a uiwebview is clicked.
First, are you sure about your method signature for the shouldStartLoadWithRequest delegate method?
Did you really override the default method to have it call:
-(BOOL)webView2:(UIWebView*)webView2 shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
???
Or should you instead be replacing "webview2" with "webView" there?
Even if you did, the naming convention would be very confusing.
The default implementation is for a class named "UIWebView", but the delegate method references "webView".
But in your case, you have a class called "webView2", and you're calling a delegate method that should be named:
-(BOOL)webView2:(webView2 *)webView2 shouldStartLoadWithRequest...
Doesn't look right at all.
Somehow I think the problem is mixed up in there. But maybe I'm wrong. So the second question is, have you set a breakpoint at the beginning of your shouldStartLoadWithRequest method to see if it ever gets called?
When you say it "doesn't work", what does that mean? How far does it get?
If it actually gets to the method, then perhaps the problem is that the URL it contains is formatted differently than the string you're looking for. Perhaps the trailing '/' isn't there or "www." is there.
Edit:
I would try something like this:
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
NSRange rangeOfGoogle = [request.URL.absoluteString rangeOfString:#"google.com"];
//Check if special link
if (rangeOfGoogle.location != NSNotFound) {
//Here present the new view controller
ViewController8 *viewController = [[ViewController8 alloc] initWithNibName:nil bundle:nil];
[self presentViewController:viewController animated:YES completion:nil];
return NO;
}
return YES;
}
I hope this will work for you
-(BOOL)webView:(UIWebView*)webView2 shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *url = request.URL;
NSString *urlString = url.absoluteString;
//Check if special link
if ( [ urlString isEqualToString: #"http://google.com/" ] ) {
//Here present the new view controller
ViewController *ViewController8 = [[ViewController alloc] init];
[self presentViewController:ViewController8 animated:YES completion:nil];
return NO;
}
}
return YES;
}
it works for me.
I am trying to let my iOS app pull from a text file on a server and display it in a Text view. This works fine if I just do this by setting the url in the viewDidLoad method. But if I do it the way I need to, a button click calls a method that sets the url based on which button is clicked and then populates the Text view also while moving to the view controller, then the Text view does not receive any text.
I am not really sure if this has anything to do with it but could it possibly be because I am using one button that has both a triggered segue to move to the next view controller and then a sent event in order to pull the information? Could it be doing it out of order or something?
Here is my code:
#import "ViewController.h"
#import "STTwitter.h"
#interface ViewController ()
{
STTwitterAPI *twitter;
}
#property (weak, nonatomic) IBOutlet UITextView *scheduleText;
#property (weak, nonatomic) IBOutlet UITextView *tweetText;
#property (weak, nonatomic) IBOutlet UIScrollView *mScrollView;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//pull from server to populate schedule
//[self pullInfo:(1)];
//load tweets
//[self callTwitter];
//set scroll view size
_mScrollView.contentSize = CGSizeMake(320, 300);
}//end viewDidLoad
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}//end didReceiveMemoryWarning
- (void) pullInfo: (int) page
{//pull information from server
NSError* err;
NSURL* url = nil;
if (page == 1)
url = [NSURL URLWithString:#"http://www.mckendree.edu /aecschedule1.txt"];
else if (page == 2)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule2.txt"];
else if (page == 3)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule3.txt"];
else if (page == 4)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule4.txt"];
else if (page == 5)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule5.txt"];
else if (page == 6)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule6.txt"];
else if (page == 7)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule7.txt"];
else if (page == 8)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule8.txt"];
else if (page == 9)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule9.txt"];
else if (page == 10)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule10.txt"];
else if (page == 11)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule11.txt"];
else if (page == 12)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule12.txt"];
else if (page == 13)
url = [NSURL URLWithString:#"http://www.mckendree.edu/aecschedule13.txt"];
NSData *htmlData = [NSData dataWithContentsOfURL:url];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:htmlData options:#{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: #(NSUTF8StringEncoding)} documentAttributes:nil error:nil];
//retrieve the text if there was no reading error
if (err != nil)
printf("Error retrieving text");
else
{
[_scheduleText setAttributedText:attrString];
[_scheduleText sizeToFit];
[_scheduleText setTextColor:[UIColor whiteColor]];
}//end else
}//end pullInfo
- (IBAction)settingsClicked:(id)sender
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:#"McK AEC" message:#"Developed by: Sean Boehnke" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {}];
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];
}//end settingsClicked
- (IBAction)time1Clicked:(id)sender
{
[self pullInfo:(1)];
}//end time1Clicked
- (IBAction)time2Clicked:(id)sender
{
[self pullInfo:(2)];
}//end time2Clicked
- (IBAction)time3Clicked:(id)sender
{
[self pullInfo:(3)];
}//end time3Clicked
- (IBAction)time4Clicked:(id)sender
{
[self pullInfo:(4)];
}//end time4Clicked
- (IBAction)time5Clicked:(id)sender
{
[self pullInfo:(5)];
}//end time5Clicked
- (IBAction)time6Clicked:(id)sender
{
[self pullInfo:(6)];
}//end time6Clicked
- (IBAction)time7Clicked:(id)sender
{
[self pullInfo:(7)];
}//end time7Clicked
- (IBAction)time8Clicked:(id)sender
{
[self pullInfo:(8)];
}//end time8Clicked
- (IBAction)time9Clicked:(id)sender
{
[self pullInfo:(9)];
}//end time9Clicked
- (IBAction)time10Clicked:(id)sender
{
[self pullInfo:(10)];
}//end time10Clicked
- (IBAction)time11Clicked:(id)sender
{
[self pullInfo:(11)];
}//end time11Clicked
- (IBAction)time12Clicked:(id)sender
{
[self pullInfo:(12)];
}//end time12Clicked
- (IBAction)time13Clicked:(id)sender
{
[self pullInfo:(13)];
}//end time13Clicked
#end
So based on your description of the issue and your comments there're a few fundamental things that are wrong here. First and foremost, the reason why this will not populate data on your pushed viewController is because you are setting the attributed text on scheduleText which is an instance variable on ViewController. If you are pushing another viewController after those buttons are pressed, then it makes perfect sense that the controller you're pushing would not have this data set because you didn't set it there, you set it on the previous controller. This data has no reason to assume you actually meant to pass it forward. That's just simply not what you asked it to do. If your intent is to pass the data forward, and you have your heart set on storyboard segues you will need to implement prepareForSegue and expose a property you can use to configure the new viewController as it's being prepared for presentation.
Sorry for the wall of text, but this is my recommendation to get through this.
First step, on your storyboard, give all of your buttons hooked up to segues button tags in the preferences tab of the right pane of interface builder. You should tag them 1 through 13 (tradition says start at 0 but this will make the next step simpler for our purposes.)
Next, get rid of all those IBActions for the buttons. We aren't going to need them anymore and they're cluttering your class. You MUST also unhook them in your storyboard after you delete the methods or your app will crash with an error that says "this class is not key value coding-compliant"
Next you need to implement the method -prepareForSegue on your viewController to do the rest of your heavy lifting
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSAttributedString *attrString;
if ([sender isKindOfClass:[UIButton class]]) {
NSUInteger seguePageNumber = ((UIButton *)sender).tag;
attrString = [self pullInfo:seguePageNumber];
}
YourViewControllerClass *vc = (YourViewControllerClass*)[segue destinationViewController];
vc.attributedTextPropertyIExposed = attrString;
//This property needs to be exposed in the new VC's header file. Once the new controller presents you can then use this property to set the string the way you want.
}
As a bonus, here's a pull info method that I referenced above that I find much easier to read.
- (NSAttributedString *)pullInfo:(NSUInteger)pageNumber
{
NSString* urlString = [NSString stringWithFormat:#"http://www.mckendree.edu/aecschedule%lu.txt", (long)pageNumber];
NSURL *url = [NSURL URLWithString:urlString];
NSData *htmlData = [NSData dataWithContentsOfURL:url];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithData:htmlData options:#{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: #(NSUTF8StringEncoding)} documentAttributes:nil error:nil];
return attrString;
}
it's been almost a week of reading and trying all of these different solutions from this website and others .. but unfortunately nothing work ..
I'm trying to develop a News app (basically, main page and Details page) .. I want to use two different uiwebviews in two view controllers .. For example: The FirstView includes the First uiwebview .. and this uiwebview shows the page (index.htm ) which includes many different news (links).. when the user click on any link ( e.g. details.htm?Id=..) it shows that link in the Second uiwebview in the SecondView controller ...
what I need exactly is, when user click on a link on uiwebview1, it directly open the view controller2 (SecondView) and open that link on the webview2 ... I know it's by using shouldStartLoadWithRequest as ive seen many ( if not all ) examples of how to use it .. but it never worked with me .. the second view controller can never be shown ..as I also set the delegate = self ..
I really tried to do it, but as i'm new ios developer .. I really need some help to get this done ... and i would really appreciate more if someone gives me a link to download the example, not because of anything, but I sometimes find it difficult to put the code on the right place ...and this is might me my problem ...
Many thanks ...
=========
I found this solution on Within a (BOOL)webView: How to open a URL clicked in UIWebView that opens a Modal UIWebView
and after much work .. all errors disappeared .. but still cant move the second view controller .. it never shown .. I used this code :
this is in the viewcontroller.h
#property (nonatomic, strong) IBOutlet UIWebView *webView;
//- (IBAction)prepareForSegue;
#property (strong, nonatomic) NSURL *url;
#property (strong, nonatomic) NSURL *targetUrl;
and this is on the viewcontroller.m
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
//Gets the link.
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
NSURL *URL = [request URL];
NSLog(#"url:%#",request); //Get's the url itself
// [self.navigationController pushViewController:SecondView animated:YES];
// [secondView release];
self.webView.delegate = self;
// ViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondView"];
// [self.navigationController pushViewController:controller animated:YES];
//
if ([[URL scheme] isEqualToString:#"http"] ||
[[URL scheme] isEqualToString: #"https" ]) {
targetUrl = url;
[self performSegueWithIdentifier:#"SecondView" sender:self];
return NO;
}
return YES;
}
return YES;
}
and before that
#synthesize webView;
#synthesize targetUrl;
#synthesize url;
and finally :
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(#"Source Controller = %#", [segue sourceViewController]);
NSLog(#"Destination Controller = %#", [segue destinationViewController]);
NSLog(#"Segue Identifier = %#", [segue identifier]);
if ([segue.identifier isEqualToString:#"SecondView"]) {
ViewController *wVC = [segue destinationViewController];
wVC.url = targetUrl ; // replace article.url with your url.
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidLoad {
NSURL *urla= [NSURL URLWithString:#"Index.htm"]; NSURLRequest *requestURL = [NSURLRequest requestWithURL:urla]; [webView loadRequest:requestURL];
//
I exactly copied the code above in my project .. and I believe there is a very tiny mistake ... it doesn't show my SecondView at all when I click on links from index.htm... what should I change on that code ...
Many thanks ...
Your main problem is that you don't have any segue defined in your storyboard. If you connect your two view controllers with a segue, name it "SecondView", and uncomment the following line...
self.webView.delegate = self;
...you'll get past your current problem.
(When the second controller displays, it doesn't seem to load the new URL...but that's some different problem.)
edit 1
I am adding some code to indicate its state after I have tried to work with codeInOrange's answer so far which so far behaves like my code originally behaved, that is sample link shows up at first in the text field and can be altered by the user, but when the user returns to the VC, any new link text has been replaced by the original sample link. My reason for posting this additional code is to try to reconnect with codeInOrange's promising answer because I am misunderstanding the logical flow of his original suggestions and his later comments.
In the current Storyboard I am leaving the Text field and the Placeholder Text empty because the sample link seems to be adequately supplied by the viewDidLoad method below.
- (void)viewDidLoad
{
[super viewDidLoad];
self.urlNameInput.text = #"sample http";
// Do any additional setup after loading the view, typically from a nib.
self.urlNameInput.clearButtonMode = UITextFieldViewModeAlways;
self.urlNameInput.clearsOnBeginEditing = NO;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == self.urlNameInput) {
[textField resignFirstResponder];
[self processPbn];
}
return YES;
}
- (void)viewDidAppear:(BOOL)animated
{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
// self.urlNameInput.text = appDelegate.stringForTextField;
appDelegate.stringForTextField = self.urlNameInput.text;
}
- (void) processPbn
{
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:self.urlNameInput.text] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[NSURLConnection sendAsynchronousRequest:theRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *connection, NSData *data, NSError *error)
{
// lots of detail code has been elided in this method
self.iboard = 0;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:toMatch options:NSRegularExpressionDotMatchesLineSeparators error:&error];
for (NSTextCheckingResult* board in [regex matchesInString:string options:NSRegularExpressionDotMatchesLineSeparators range:NSMakeRange(0, [string length])])
{
if (self.iboard>0) {
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.stringForTextField = self.urlNameInput.text;
}
}];
}
edit 1
edit 0
I do not want to preserve the text between application shutdowns and launches, so the answer using NSUserDefaults is not quite what I need.
Also, it appears from my trials that the solution suggested by Michael Dautermann which suggests either putting my intialization text in viewDidLoad or in the Xib or Storyboard, does not work because the text always returns to its initial value upon return to the VC (likely because the viewDidLoad method is triggered), so I think I do need to create an ivar in my AppDelegate.m as I asked in my original question, and not in my ViewController.m viewDidLoad, to get the desired result, apparently. Perhaps it would be easier to create a B00L ivar in AppDelegate.m which is a flag that tells whether original text or current text is desired. But I cannot figure out how to do that, either. So, please consider this edit in your answer.
edit 0
My AppDelegate.m contains the following code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
BDViewController *vc = [sb instantiateInitialViewController];
self.viewController = (id)vc;
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
In the VC I want an ivar, an NSString, to be set at launch so that it can be the example text in my UITextField. Later I want that UITextField to be adjusted to an new value when the user supplies valid text into a UITextField.
Currently in my VC.h, the text field is declared and is synthesized in VC.m as follows .
#property (nonatomic, strong) UITextField *urlNameInput;
#synthesize urlNameInput;
I have tried putting the following code into didFinishLaunchingWithOptions: but do not see the desired text when I run the app.
self.viewController.urlNameInput.text = #"example http";
How can I programmatically accomplish my goal of initializing the UITextField?
Put that "urlNameInput.text =" bit into your view controller's "viewDidLoad" method, instead of the "didFinishLaunchingWithOptions:" method (where your view controller is not likely yet instantiated.
Even better than that, just set the initial text in your storyboard or XIB file and then you can programmatically adjust it later on.
Ok I'm having a hard time understanding what you're trying to do but creating an NSString iVar on your app delegate (although there are many other solutions) will allow you to set the textfield text to whatever you want when that VC comes back on the screen.
In your AppDelegate.h
#property (strong, nonatomic) NSString *stringForTextField;
This way you can initialize your textfield text when the view is loaded (viewDidLoad)
self.urlNameInput.text = #"example http";
then whenever that text value needs to be changed (say for example in textFieldShouldReturn in the other view controller. I'm assuming you have another textfield based on your question)
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.stringForTextField = textField.text;
and in viewDidAppear in the VC with the textField set that value.
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
self.urlNameInput.text = appDelegate.stringForTextField;
probably not the best way to go about it, but it will work.
EDIT
Ok in viewDidAppear:
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if ([appDelegate.stringForTextField isEqualToString:#""]){
self.urlNameInput.text = #"example http";
} else {
self.urlNameInput.text = appDelegate.stringForTextField;
}
Now what this will do is if the user goes to another view controller, and comes back, the text field text will be what the user last entered, unless in another view controller, stringForTextField is updated to some new value. If this still does not work, look at your processPbn method to make sure the if clause is entered and that value is set. Otherwise it will always say "example http"
I'm not understanding why it's unimportant to persist the previous value across application launches, especially when it is beneficial to your users to have it persist only during the application lifecycle. codeInOrange's answer works by adding a property to the AppDelegate. The only thing I would add to his answer is a conditional if() . If you want to do it without any properties, you can still use the NSUserDefaults.
At the top of your ViewController.m file
#define SetHTTPString(string) [[NSUserDefaults standardUserDefaults]setObject:string forKey:#"HTTPString"] //no semicolon
#define GetHTTPString() [[NSUserDefaults standardUserDefaults]objectForKey:#"HTTPString"] //no semicolon
Then, in viewWillAppear...
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString *httpString = GetHTTPString();
if (httpString) {
self.urlNameInput.text = httpString;
} else {
self.urlNameInput.text = #"Example http";
}
}
Next, in the method where the user enters text and "enters it"
...methodToEnterURL {
SetHTTPString(self.urlNameInput.text);
}
Finally, if you absolutely want to destroy the value in the NSUserDefaults, add this method to your AppDelegate's didEnterBackground method:
[[NSUserDefaults standardUserDefaults]setObject:#"Example http" forKey:#"HTTPString"];
This is a perfect usage for NSUserDefaults. When the user enters something just store it in NSUserDefaults. Check to see if the NSUserDefaults entry is blank on each launch, and if so just display the original string.
Save the text in NSUserDefaults with something like:
[[NSUserDefaults standardUserDefaults]setObject:#"yourNewString" forKey:#"userTextEntered"];
And then just check it on each launch:
if([[NSUserDefaults standardUserDefaults] objectForKey:#"userTextEntered"])
{
//display the user entered string
}
else
{
//display the string that you want to display prior to text being entered
}
However, this solution is only necessary if you want to preserve the text between application shutdowns and launches.
The code below assumes that the Storyboard contains the initial, default Text (of at least 3 characters length).
I really appreciated the help I got from others, especially from codeInOrange . I actually believe this is codeInOrange's solution, but I was never able to quite put his pieces together until I finally stumbled upon this one.
I hope this is really a valid answer, and apologize to all if I did not state my question clearly or if I mistook others' valid answers, especially codeInOrange.
//
// ViewController.m
// StickyPlaceholder
//
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize textInput;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if (!appDelegate.stringForTextField)appDelegate.stringForTextField = self.textInput.text ;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
if (textField == self.textInput) {
[textField resignFirstResponder];
// next line is dummy processing
if (self.textInput.text.length>2)appDelegate.stringForTextField = self.textInput.text;
}
return YES;
}
- (void)viewDidAppear:(BOOL)animated
{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
self.textInput.text = appDelegate.stringForTextField;
}
#end
In my app I need to display stores around the user location. Each store has name, tagline, and a logo, and we want to display all these information on the callout bubble that comes up on the map once I touch a pin. Considering that I need to load the image remotely, and that waiting three seconds to see the callout after touching the pin is not acceptable, what would be the best solution?
The file of an array of around 20 stores is like 10kb, but if we load the logo for all of them straight away, maybe it would be like 110kb (considering an estimate of 5kb per image), which I`m not sure if it is a good idea.
In one of my project that case works just fine.
I'm using SDWebImage for the remote async load of the image.
I did:
subclass the MKPinAnnotationView:
.h
#interface TLStoreResultMapAnnotationView : MKPinAnnotationView
#property (assign)BOOL imageSet;
#end
.m
#import "TLStoreResultMapAnnotationView.h"
#import "TLStoreResultMapAnnotation.h"
#import "UIImageView+WebCache.h"
#implementation TLStoreResultMapAnnotationView
#synthesize imageSet=_imageSet;
- (void)layoutSubviews {
if(self.selected && (!self.imageSet)) {
TLStoreResultMapAnnotation *annotation = (TLStoreResultMapAnnotation *)self.annotation;
NSURL *url = [NSURL URLWithString:[annotation.store.imageURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
UIImageView *storeImageView = (UIImageView *)self.leftCalloutAccessoryView;
storeImageView.frame = CGRectMake(storeImageView.frame.origin.x,storeImageView.frame.origin.y,30.0,30.0);
storeImageView.contentMode = UIViewContentModeScaleAspectFill;
storeImageView.clipsToBounds = YES;
[storeImageView setImageWithURL:url
placeholderImage:[UIImage imageNamed:#"webloading.png"] options:SDWebImageCacheMemoryOnly];
self.imageSet = YES;
}
[super layoutSubviews];
UIImageView *storeImageView = (UIImageView *)self.leftCalloutAccessoryView;
storeImageView.frame = CGRectMake(storeImageView.frame.origin.x,storeImageView.frame.origin.y,30.0,30.0);
}
#end
of course your need to adapt the code a bit.