TodayViewController class in iOS Today widget not being read? - ios

My TodayViewController class is implemented as follows:
#import "TodayViewController.h"
#import <NotificationCenter/NotificationCenter.h>
#interface TodayViewController () <NCWidgetProviding>
#end
#implementation TodayViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"yeehaw");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
NSLog(#"gitalong");
completionHandler(NCUpdateResultNewData);
}
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{
NSLog(#"yowza!");
return UIEdgeInsetsZero;
}
#end
Basically this is the boilerplate implementation that XCode provides when you create a Today target in your app. The only changes I've made are to add some NSLog() calls in each of the functions, and to remove the default left margin in the widgetMarginInsetsForProposedMarginInsets() function (as per the method in this SO thread).
However, when I look at the system log output, none of my NSLog statements are being output, and the default left margin has not gone away, so I'm thinking that for some reason, my app is not reading/processing the TodayViewController class at all, even though it is otherwise displaying my MainInterface storyboard correctly.
Does anyone know why this might be happening?
UPDATE
A detail I forgot to mention is that the MainInterface.storyboard file I was using to implement the interface was copied into this project from another version of the same project. I was able to fix this problem by recreating the entire project from scratch and recreating the interface from scratch as well, so the MainInterface.storyboard file I used in the "working" project was the original one generated by XCode. While this strategy fixed my immediate problem, I still don't understand why the storyboard file that I imported from another project didn't work. This poses a problem for interface reuse. I'd still like to know how to link an imported storyboard file to a custom ViewController.

Related

Multiple Class in one file

Recently I was studying the possibility of creating multiple classes in only one file, for this I created a class of UIViewController with a .xib file, the structure of the file is as follows:
MyFristViewController.h
#import <UIKit/UIKit.h>
#interface MyFristViewController : UIViewController
#end
#interface MySecondViewController : UIViewController
#end
MyFristViewController.m
#implementation MyFristViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Frist View Loaded");
}
#end
#implementation MySecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Second View Loaded");
}
#end
My doubt is: How does the system know that is to perform the methods contained in the class called 'MyFristViewController'?
I already tried to modify the custom class in interface builder, tried to change the position of the classes in the file and the system continues running only the existing methods inside the 'MyFristViewController' class why?
How does the system know that is to perform the methods contained in the class called 'MyFristViewController'?
The filenames are irrelevant. When looking at a class, for the most part, the code between #implementation <#ClassName#> and #end is used.
Additional customization of classes can be added through categories and class extensions. These can also be specified in the same file, or different files, because (again) the filenames are irrelevant.
Generally, you should have one class per file to make it easy to read and find your code. See How many classes should a programmer put in one file? for additional discussion.
My doubt is: How does the system know that is to perform the methods contained in the class called 'MyFristViewController'?
Because the methods are in the #implementation block of MyFristViewController.
I already tried to modify the custom class in interface builder, tried to change the position of the classes in the file and the system continues running only the existing methods inside the 'MyFristViewController' class why?
Probably because you've linked them to the methods in first #interface section in your header file. Control-drag to the actual method you want to bind to. It's not clear what problem you're actually seeing.
That said, this is a terrible idea. Put each view controller in its own file. It'll work in one file, but it will create lots of confusion, as you're seeing.
I have worked on projects that define multiple classes in a single file. I loathe this practice. I find it very disorienting and I waste a lot of time searching for where the classes are defined/implemented.
I would advise you not to do this. It ends up being very confusing.

How to make a call with button in iOS

This is my first attempt at creating an app. and using Xcode.
The reason this question hasn't been answered before is because there are no answers to my question from the perspective I'm currently at, namely, I've followed the instructions on this URL to creating an app:
http://www.wikihow.com/Make-an-iPhone-App
I have got to the Part 3 of 5: Creating the App, section 6 - thereafter my question is not answered - which is how to make my button make a call when tapped.
Therefore I am now, in Xcode at the point where (remember I followed those instructions on the linked page) I have my one button on the screen but ALL the instructions I could find doesn't address exactly what I need to do to make that button make a call.
Some examples show code like here: Making a Button Call a Phone Number in iOS
but doesn't tell me what to do with that code, I'm new to all of this so finding out the exact steps from this point has been brutal at best. Also, all the code I have tried pasting into sheets that have code in them (by clicking around) the code shows errors - all the code I've obtained from the web.
Any help?
P.S. On this page, a poster says that there is actually a button that is associated with making calls, but I again, know not where to find this…
http://www.insanelymac.com/forum/topic/126918-initiating-a-call-on-iphone/
Open your xib/storyboard side-by-side with your view controller implementation, hold Control and drag your button (interface builder) to your implementation. Xcode should generate an IBAction for you automatically.
On your code, call:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel:911"]];
Basically you need to add the code you found into a 'method' in your appdelegate.m file. This 'method' is a segment of code that is executed whenever it is told to.
So in appdelegate.m, add in the lines above #end
- (IBAction)makeCall:(id)sender {
}
Now paste the line of code you found in between the two curly brackets. Now whenever 'makeCall' is called that line of code you found will be executed which will make a phone call (hopefully)
The next step is making the button tell the 'makeCall' method to run. In order to do this you need to 'declare' the makeCall method, it's the equivalent of putting an item up on sale on eBay: in the previous step you made the item(method), now you want to show the world it's available.
Appdelegate.h is the equivalent to eBay/Craigslist/gumtree in this scenario: add this line of code anywhere above #end:
-(IBAction)makeCall:(id)sender;
Now the final step is to link your button to this, and it's the easiest part. Go back to your interface builder and click on your button. Right click the button and drag a line to the blue box on the left called 'AppDelegate' (this is the files you added code to earlier, remember?) and select makeCall from the little list that pops up. You have successfully linked your button to your method, so now when you click the button you should be able to make a call!
If you want to know more about the specifics of the code you just added, IBAction is the type of method, and it means a method that can have buttons linked to it in interface builder. The (id)sender part means that whenever the method is called, the object/button that called the method is passed along so the method can see who 'sent' for it.
Edit: Ok since you're using storyboards we'll need to create what's called a 'view controller'. This basically delegates and controls (hence the name) whatever is on your phone's screen.
So create a new class by going to file -> new -> cocoa class, and in the fields call it ViewController and make it a subclass of UIViewController.
Now we'll need to copy all the code that we added to appdelegate.h and appdelegate.m over to viewcontroller.h and viewcontroller.m, with the code we added to the appdelegate.h being copied to the same place in viewcontroller.h etc.
They should look something like this:
ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
-(IBAction)makeCall:(id)sender;
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)makeCall:(id)sender {
}
#end
With makeCall having the line of code that you pasted in it earlier.
Now go back to interface builder and click on the little yellow square inside a cube above your screen, and then click on the newspaper-looking icon on the right hand side:
In the class field type in ViewController (it should automatically complete it for you) and then go to the arrow icon tab (which is known as bindings):
Click and drag the little circle beside make call onto your button, and select one of the 'touch down' options that appear. These just mean when to call that method i.e as soon as the user presses the button or when they lift their finger off it. They should now be linked. Give it a try and let me know how it works.

Category is implementing a method which also be implemented in primary class : `viewWillAppear:`

I'm trying to category UIViewController to override viewWillAppear:. But getting this warning.
Category is implementing a method which also be implemented in primary
class
#implementation UIViewController (ViewWillAppearCategory)
-(void)viewWillAppear:(BOOL)animated
{
//.........
}
#end
I want to do some stuff during view appear in all screen, So I don't want to touch in all screen. that's why, go with category.
I may implement some method in sub class and I can call that method in all VC(all Screen). But I don't want this. It automatically invoke in view will appear call. Is this any idea to do this or did any mistake in above?
Note: This code will only appear in development phase for some testing purpose. So I'll remove this code when go with app store. So It should be easier task during removal, that is I won't touch all screen. I won't keep this code during submission to app store.
In such cases you must try Method Swizzling, a very nice formed concept which allows you to change the implementation of an existing selector.
For more details and code please visit the link below.
http://nshipster.com/method-swizzling/
categories are for adding new methods, not overriding existing ones. Maybe make a subclass of UIViewController, say, MyUIViewController, with this code:
-(void) viewWillAppear:(BOOL) animated {
// do your "category" stuff
}
then make all your other UIViewControllers subclasses of MyUIViewController with this code:
-(void) viewWillAppear:(BOOL) animated {
[super viewWillAppear:animated];
// rest of code for this class
}
I understand the reasons why you want to have a simple solution to test something on all screens and remove it easily, however:
You can not call super in a category, and not calling [super viewWillAppear:] may have unexpected results depending on the class and its particular implementation.
Swizzling methods is a hack and as you'll remove it from your final version, your testing version becomes useless as it may behave very differently.
On the other hand creating a UIViewController superclass where you properly override viewWillAppear: is not that complicated:
The code will belong only to a single class. No need to repeat/maintain code for every "screen".
You only need to change the other controllers' superclass and Nibs or Storyboards references once.
You can keep the superclass for both testing and release and the behavior will be similar.
You can do so many more things in a superclass than in a category.
Ultimately it would be interesting to know what are you trying to achieve. You could probably achieve similar things by implementing a UINavigationControllerDelegate and keep track of controllers getting pushed and popped.
As for viewWillAppear documentation:
This method is called before the receiver’s view is about to be added
to a view hierarchy and before any animations are configured for
showing the view. You can override this method to perform custom tasks
associated with displaying the view. For example, you might use this
method to change the orientation or style of the status bar to
coordinate with the orientation or style of the view being presented.
If you override this method, you must call super at some point in your implementation.
Again, you can't do that from a category.
As you are saying the code is going to be executed only in debug mode. Then why do you worry about warnings let the warning come you continue your work when it comes to release you remove your Category.
If you don't even need to see the warning your go with your same answer like
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
-(void)viewWillAppear:(BOOL)animated
{
NSLog(#"I get callback here too");
}
#pragma clang diagnostic pop
But I would say to go for subclassing because removing the existing class is also not that hard in XCode tool.
What you want to achieve defeats the purpose of a Category. However, there's another way aside from subclassing UIViewController but you have to touch the viewWillAppear method for each controller.
//UIViewController+CustomCategory.h
#interface UIViewConctroller (CustomCategory)
- (void)performCustomization;
#end
//UIViewController+CustomCategory.m
#implementation UIViewController (CustomCategory)
- (void)performCustomization {
// Do custom stuff…
}
#end
Then in each controller
//MYViewController.m
#import "UIViewController+CustomCategory.h"
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self performCustomization];
}

Error when using MKMapView

I created a single view application with story boards. All I had in my view was MKMapView, thats it. It compiles without errors or warning but when I run it, I get this error in my console window:
<Error>: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedImageBlockData: readSession [0x8ab5750] has bad readRef [0x14b79c70]
I'm using Xcode 4.3 and iPhone Simulator 5.1. Any thoughts?
.h File
#import UIKit/UIKit.h
#import CoreLocation/CoreLocation.h
#import MapKit/MapKit.h
#interface WhereamiViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>
{
IBOutlet MKMapView *worldView;
IBOutlet UIActivityIndicatorView *activityIndicator;
IBOutlet UITextField *locationTitleField;
}
#end
.m file
#import "WhereamiViewController.h"
#interface WhereamiViewController ()
#end
#implementation WhereamiViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Just ran into this:
Simple Fix: Make sure to check the box for "shows user location" for the MapView in interface builder.
Probably i should not answer a question of almost a year, but i was having the same issue and the cause was that i was calling CLLocationManager *startUpdateLocation* on viewDidLoad method, when i change it to viewWillAppear the issue dissapeared.
That looks to me like a bug in the framework. Report it using the Apple Bug Reporter and see if it's a known issue.
My PNG's contained some transparent parts and I think this caused the problem, because after removing these parts the error disappeared. Maybe I had some error in my PNG files, because transparency should be supported.
I also ran into the same problem. I solved it by commenting out all the code and compile the program. Then I uncommented each method one by one compiling after each time. For some reason that seemed to get rid of the error for me.
Correct ur codes as below, and create the outlet of map view.
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
Well I'm doing a much simpler project so I'm not sure if it will help you. But I'll show you my code anyway. You may want to just start with this and then see if you can build from there.
So for the ViewController.h it should read......
#import <UIKit/UIKit.h>
#import <MapKit

RootViewController cannot use 'super' because it is a root class

While going through a tutorial which uses a navigation based- application, I decided to create a Navigation-Based Application with my 3.2.6-Xcode and open it with Xcode 4.2 for following the tutorial with that version.
But when I open the same project in Xcode 4.2 (without changing or adding any code), the 4.2 Xcode gives me 2 errors saying:
RootViewController cannot use 'super' because it is a root class
Right now, my Xcode has 4 class-files: RootViewController.h, RootViewController.m, SaveUpAppDelegate.h and SaveUpAppDelegate.m. The error is in RootViewController.m:
- (void)dealloc {
[super dealloc];
}
and
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
I already searched through the internet and found this discussion (http://stackoverflow.com/questions/10113669/xcode-4-3-2-gives-error-cannot-use-super-because-it-is-a-root-class) and they say that the reason might be that the controller is that the developer forgot the superclass in the #interface line. That doesn't fit to my case, because I (or better: Xcode 3.2.6) didn't forget the superclass in RootViewController.h...
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController {
}
#end
right now, I commented those critical lines out and it works fine, but I'm sure, I'll need those lines since most of the automatic created lines in the m-file are done with [super ....].
How to solve the problem?
My resolution was more simple. There was a misspelling in the #import "ClassHere.h" in the .m file. This resolved the issue I had.
Clean. It's an option under "Run". It removes all the build files that are automatically generated.

Resources