Objective C - How to call UI-process from non-UI class - objective-c

I'm trying to get the user position in iOS.
I guess the problem could be related to the dispatch_async.
I don't get errors during compilation but only the init function is called and the locationManager never gives an update.
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
 
#interface LocationC: UIViewController <CLLocationManagerDelegate> {
    CLLocationManager *locationManager;
}
 
#end
 
#implementation LocationC
 
- (instancetype) init {
    self = [super init];
    if (self) {
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        locationManager.distanceFilter = kCLDistanceFilterNone;
        locationManager.desiredAccuracy = kCLLocationAccuracyBest;
          
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
            [locationManager requestWhenInUseAuthorization];
        [locationManager startMonitoringSignificantLocationChanges];
        [locationManager startUpdatingLocation];
    }
    return self;
}
 
 //never called
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    NSLog(#"test")
}
#end
 
 
class LocationGet : public claid::Module
{
    public:   
        void initialize()
        {
            dispatch_async(dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
                //Background Thread   
                dispatch_async(dispatch_get_main_queue(), ^(void){
                    //Run UI Updates
                    LocationC *example = [[LocationC alloc] init];
                });
            });   
        }
};

There might be a scenario in which the authorization status is not "Granted" when you call startMonitoring...
If the user sees the page for the first time and and location permission hasn't been authorized yet, requestWhenInUseAuthorization will display the dialogue, but you need to implement locationManager(_:didChangeAuthorization:) in order to know when the status has changed.
See this article:
https://developer.apple.com/documentation/corelocation/cllocationmanager/1620562-requestwheninuseauthorization
It says:
After the user makes a selection and determines the status, the location manager delivers the results to the delegate's locationManager(_:didChangeAuthorization:) method.
-- Update --
After another look, you should store a reference to the example instance, or else it would dealloc from memory before any location update is received. A UIViewController instance should be presented or pushed from another UIViewController instance, or alternatively it can be set as the root view controller of the application. Just instantiating it is not enough.

You have to wait for user permission if it's not explicitly given before starting listening to the location updates, so you enable your listener only when this permission choice is delivered:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationC: UIViewController <CLLocationManagerDelegate>
#property (nonatomic, readonly) CLLocationManager *locationManager;
#end
#implementation LocationC
- (instancetype) init {
if (self = [super init]) {
_locationManager = [CLLocationManager new];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self locationManagerDidChangeAuthorization:_locationManager];
}
return self;
}
#pragma mark CLLocationManagerDelegate
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
switch (manager.authorizationStatus) {
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways:
[self startLocationListener];
break;
case kCLAuthorizationStatusNotDetermined:
[manager requestWhenInUseAuthorization];
break;
default:
[self stopLocationListener];
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
NSLog(#"New locations: %#", locations);
}
#pragma mark Private
- (void)startLocationListener {
[_locationManager startMonitoringSignificantLocationChanges];
[_locationManager startUpdatingLocation];
}
- (void)stopLocationListener {
[_locationManager stopMonitoringSignificantLocationChanges];
[_locationManager stopUpdatingLocation];
}
#end
Also, be advised that you will need to provide the user with some message explaining why exactly you request location permissions by adding NSLocationWhenInUseUsageDescription key in your app's Info.plist
EDIT:
Somehow I completely missed the part that LocationC is a view controller itself. With the extra details you provided in the comments, it seems to me that this instance is not retained by Cocoa Touch framework classes, so your example gets deallocated straight away.
Here are a couple of Cocoa Touch tweaks important to understand: UIKit expects an instance of any UIViewController (or its subclasses) to represent some view on the screen, thus if you expect LocationC to be purely responsible for non-UI logic, you should not subclass it from a UIViewController class and instead you may want to create as another controller property:
// Some view controller interface section
#interface ViewController: UIViewController
...
#property (strong, nonatomic, readonly) LocationC *locationListener;
...
#end
// Some view controller implementation section
#implementation ViewController
...
- (void)viewDidLoad {
[super viewDidLoad];
_locationListener = [LocationC new];
}
...
#end
If you instead expect this object to really represent a separate view, and conventionally a separate screen, then you are supposed to somehow pass the presenting view controller to the point in the code where LocationC is supposed to show up:
void initialize()
{
// m_PresentingController is the membmer of the class which keeps a reference to the
// presenting controller
__weak typeof(m_PresentingController) weakController = m_PresentingController;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
...
dispatch_async(dispatch_get_main_queue(), ^{
// If the presenting controller was destroyed before response handler comes
// int play, ignore the response
if (!weakController) {
return;
}
__strong typeof(weakController) strongController = weakController;
[weakController presentViewController:[LocationC new] animated:YES completion:nil]
});
});
}
Alternatively, you can make LocationC a new root controller of your app:
void initialize()
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
...
dispatch_async(dispatch_get_main_queue(), ^{
UIApplication.sharedApplication.delegate.window.rootViewController = [LocationC new];
});
});
}

Related

any method to show user location in ios

Is there any method that take latitude and longitude as parameter and google map link or apple map link these three parameter to show user location on google map or apple map so user can use google created google map functionality like arrow direction or zoom in/out.
I don't want to use MKMapView of iOS to show user location in my app.
thanks in advance give me any cool method(latitude,longitude,google map link)as parameter.
For coordinates only, you need CoreLocation, so google that.
But if you need to show a map and arrow, you do need a maps framework. Either go for built in MKMapKit, or you can download Google Maps SDK.
First of all , Please import this framework
#import
, to import this framework , you need to select your project then go to build phases , click on link binaries with libraries and add the core location framework .
Add this code in your view controller in view didload method:-
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest; // 100 m
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
// Delegates of Mapview
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(newLocation.coordinate, 800, 800);
[map_View setRegion:[map_View regionThatFits:region] animated:YES];
if (newLocation != nil) {
NSLog(#"%f %f",currentLocation.coordinate.longitude,currentLocation.coordinate.latitude);
[locationManager stopUpdatingLocation];
locationManager = nil;
}
// Reverse Geocoding
CLGeocoder *geocoder = [CLGeocoder new];
dispatch_async(dispatch_get_main_queue(), ^{
[geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
} else {
NSLog(#"%#", error.debugDescription);
}
} ];
});
}
Don't forget to add this line in your plist file :-
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription

UIWebView Delegate : webViewDidFinishLoad not being called

I try to load an array of UIWebView with delegate associated.
for (GDataXMLElement *post in array) {
NSString *msg = [[[post elementsForName:#"message"] objectAtIndex:0] stringValue];
UIWebView *web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(#"Msg: %#", msg);
}
where msg is some HTML codes reading from XML. XML is loaded properly (verified by the NSLog line). Then in my webViewDidFinishLoad::
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
NSLog(#"WebView Height: %.1f", webView.frame.size.height);
[webviews addObject:webView];
}
I auto resize the web views and add them to a NSMutableArray called webviews. However, webViewDidFinishLoad is not called.
In the header .h file, the interface is defined as:
#interface ViewController : UIViewController<UIWebViewDelegate>
What did I miss? Is the web_view in the loop get disposed ?
p.s. It looks like a duplicate of this question, but it isn't.
Alternate Approach 1
Declared at .h:
#property (nonatomic, weak) NSMutableArray *webviews;
Then for implementation:
for (GDataXMLElement *post in array) {
NSString *msg = [[[post elementsForName:#"message"] objectAtIndex:0] stringValue];
UIWebView *web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(#"Msg: %#", msg);
[self.webviews addObject:web_view];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    CGRect frame = webView.frame;
    frame.size.height = 1;
    webView.frame = frame;
    CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
    frame.size = fittingSize;
    webView.frame = frame;
    NSLog(#"WebView Height: %.1f", webView.frame.size.height);
}
Alternate Approach 2
Instead of instantiating UIWebView in for-loop, I put it in header file.
#interface ViewController : UIViewController<UIWebViewDelegate> {
UIWebView *web_view;
}
Then change the for-loop:
for (GDataXMLElement *post in array) {
NSString *msg = [[[post elementsForName:#"message"] objectAtIndex:0] stringValue];
web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(#"Msg: %#", msg);
[self.webviews addObject:web_view];
}
In this approach, only the delegate of last message gets called.
Summary & Highlights:
My objectives:
Load all UIWebView with variable-size contents
The web views should auto fit the size of contents ( without scrolling ); that's why webViewDidFinishLoad is required.
Arrange the web views properly on current view ( or probably a UIScrollView ) in order to make it not overlapped.
You should do like this,
#interface UIViewController <UIWebViewDelegate>
{
}
#property(nonatomic, strong)NSMutableArray *webViews;
#end
////////////////
#implementation UIViewController
-(void)viewDidLoad
{
[super viewDidLoad];
webViews = [[NSMutableArray alloc] init];
for (GDataXMLElement *post in array)
{
NSString *msg = [[[post elementsForName:#"message"] objectAtIndex:0] stringValue];
UIWebView *web_view = [[UIWebView alloc] initWithFrame:CGRectZero];
web_view.delegate = self;
[web_view loadHTMLString:msg baseURL:nil];
NSLog(#"Msg: %#", msg);
[self.webViews addObject:web_view];
//i don't know why would you not add these web-views on the view controller,
// but still, here is the addition of these.
[self.view addSubView:web_view];
}
}
#end
This should make the web-views call the delegate properly on load.
If you're using ARC, the web_view is deallocated at the end of the for loop.
Here is my final solution ( hope it is useful for others ):
In Storyboard, I added a UIScrollView in the view controller, and link it with the IBOutlet.
Header file:
#import <UIKit/UIKit.h>
#import "GDataXMLNode.h"
#interface ViewController : UIViewController<UIWebViewDelegate> {
IBOutlet UIScrollView *scroll_view;
}
#property (nonatomic, strong) UIWebView *web_view;
#end
Implementation file:
float currentY;
NSArray *array;
int count;
GDataXMLDocument *doc;
- (void)viewDidLoad
{
[super viewDidLoad];
currentY = 0;
count = 0;
[self loadXML];
}
- (void)loadXML {
// Some codes to load the XML contents into array variable
[self loadWebView];
}
- (void)loadWebView {
if(count < array.count) {
GDataXMLElement *post = [array objectAtIndex:count];
NSString *msg = [[[post elementsForName:#"message"] objectAtIndex:0] stringValue];
count++;
self.web_view = [[UIWebView alloc] initWithFrame:CGRectMake(10, currentY, 300, 1.0f)];
self.web_view.delegate = self;
[self.web_view setHidden:YES];
[self.web_view loadHTMLString:msg baseURL:nil];
[scroll_view addSubview:self.web_view];
} else {
// end the process
[scroll_view setContentSize:CGSizeMake(320, currentY + 30)];
return;
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
[webView setHidden:NO];
currentY += webView.frame.size.height + 20.0f; // 20.0f is spaces between posts
NSLog(#"WebView Height: %.1f", webView.frame.size.height);
[self loadWebView];
}

pushViewController in Xcode

I'm trying to push a view from a table cell to another view, I know that there's a lot of tutorials out there, I've tried a lot of them, been trying for 2 days and still can't get it working, here's my code..
AppDelegate.h
#import <UIKit/UIKit.h>
#class RootViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) RootViewController *rootViewController;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "RootViewController.h"
#implementation AppDelegate
#synthesize window = _window;
#synthesize rootViewController;
- (void)dealloc
{
[_window release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.rootViewController = [[[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil] autorelease];
self.window.rootViewController = self.rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
#end
RootViewController.h
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController{
NSMutableArray* array;
}
#property(nonatomic, retain)NSMutableArray* array;
#end
RootViewController.m
#import "RootViewController.h"
#import "SubLevelViewController.h"
#implementation RootViewController
#synthesize array;
- (void)viewDidLoad {
[super viewDidLoad];
array = [[NSMutableArray alloc] init];
[array addObject:#"One"];
[array addObject:#"Two"];
[array addObject:#"Three"];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release anything that can be recreated in viewDidLoad or on demand.
// e.g. self.myOutlet = nil;
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
// Configure the cell.
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SubLevelViewController *sub = [[SubLevelViewController alloc] initWithNibName:#"SubLevelViewController" bundle:nil];
sub.title = #"My First View";
[self.navigationController pushViewController:sub animated:YES];
}
- (void)dealloc {
[array release];
[super dealloc];
}
#end
and main.m
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Actually, your problem is simple, you reference self.navigationController, yet the view controller has no navigation controller set up in the AppDelegate! You're sending a message to nil, which produces nil (ergo, nothing happens). Try this in the appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.rootViewController = [[[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil] autorelease];
UINavigationController * controller = [[[UINavigationController alloc]initWithRootViewController:self.rootViewController]autorelease];
    self.window.rootViewController = controller;
    [self.window makeKeyAndVisible];
return YES:
}
Agree with CodaFi, you need to create a UINavigationController and remember it to push and pop any UIViewController if you want to keep the push/pop stack. Do not use self.navigationController.

UITableView - didSelectRowAtIndexPath Question? [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
UITableView and Selecting Items
I am building a iPad app, and have ten Items in a UITableView. When I select option "Apple" I would like it to display a apple in the UIImageView on right. When I select "Orange" I would like it to display a Orange in the UIImageView on the right, and so on.
What is the simplest piece of code to accomplish this?
Assuming you have stored your values that you are displaying in some sort of NSArray or other type of data source (I'm going to assume NSArray), then you could do something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selection = [myArray objectAtIndex:indexPath.row];
if ([selection isEqualToString:#"Apple"])
{
[myImageView setImage:[UIImage imageNamed:#"Apple.png"]];
}
elseif ([selection isEqualToString:#"Orange"])
{
[myImageView setImage:[UIImage imageNamed:#"Orange.png"]];
}
}
Building off of Thuggish Nugget's answer, you could incorporate the selection name right into the image string:
NSString *selection = [myArray objectAtIndex:indexPath.row];
[myImageView setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%#.png", selection]]];
And you could condense that down into one line.
I answered this alredy for you.
Here is the SO question
It would be a good idea to respond to that same question with a comment if u still need help with a UITableView.
Here is the answer from the other question.
Either set the cell.imageView.highlightedImage, or in the didSelectRowAtIndexPath method, change the cell.imageView.image from nil to some [UIImage imageNamed:#"myImage.png"]:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *kCustomCellID = #"com.me.foo.cell";
    UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCustomCellID] autorelease];
    cell.textLabel.highlightedTextColor = [UIColor blueColor];
    cell.imageView.image = nil;
    cell.imageView.highlightedImage = [UIImage imageNamed:#"myImage.png"];
    return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(iPadRootViewControllerTableCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Do this if you didnt set the highlightedImage in cellForRowAtIndexPath
    // [self tableView:tableView cellForRowAtIndexPath:indexPath].imageView.image = [UIImage imageNamed:#"myApple.png"];
}
Edit (adding comments from other questions answer):
To get a specific item from an array for a row, just use the indexPath.row as the objectForIndex for your array.

Why am I not getting a grey background in this program

I followed the tutorial on this page:
http://iphone-3d-programming.labs.oreilly.com/ch01.html
I got down to the part where it says, "Compile and build and you should now see a solid gray screen. Hurray!" However, when I ran the program, I just get a black screen.
These are what the files look like:
HelloArrowAppDelegate.h
#import <UIKit/UIKit.h>
#import "GLView.h"
#interface HelloArrowAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *m_window;
GLView* m_view;
}
#end
HelloArrowAppDelegate.mm
#import "HelloArrowAppDelegate.h"
#implementation HelloArrowAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
CGRect screenBounds = [[UIScreen mainScreen] bounds];
m_window = [[UIWindow alloc] initWithFrame: screenBounds];
m_view = [[GLView alloc] initWithFrame:screenBounds];
[m_window addSubview: m_view];
[m_window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[m_view release];
[m_window release];
[super dealloc];
}
#end
GLView.h
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#interface GLView : UIView {
EAGLContext* m_context;
}
-(void) drawView;
#end
GLView.mm
#import "GLView.h"
#implementation GLView
- (void) drawView
{
glClearColor(0.5f, 0.5f, 0.5f, 1);
glClear(GL_COLOR_BUFFER_BIT);
[m_context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer;
eaglLayer.opaque = YES;
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!m_context || ![EAGLContext setCurrentContext:m_context]) {
[self release];
return nil;
}
// OpenGL Initialization
GLuint framebuffer, renderbuffer;
glGenFramebuffersOES(1, &framebuffer);
glGenFramebuffersOES(1, &renderbuffer);
[m_context
renderbufferStorage:GL_RENDERBUFFER_OES
fromDrawable: eaglLayer];
glFramebufferRenderbufferOES(
GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
GL_RENDERBUFFER_OES, renderbuffer);
glViewport(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
[self drawView];
}
return self;
}
- (void)dealloc {
if ([EAGLContext currentContext] == m_context) {
[EAGLContext setCurrentContext:nil];
}
[m_context release];
[super dealloc];
}
#end
The initWithFrame is incorrect. You want to generate a framebuffer and a renderbuffer and link the two. Instead you generate two framebuffers and completely ignore one. You should also keep the references to them (the variables 'renderbuffer' and 'framebuffer') in your class, as you'll need to delete them later unless you want to leak memory.
Without fixing the second issue, I recommend:
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer;
       eaglLayer.opaque = YES;
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
       if (!m_context || ![EAGLContext setCurrentContext:m_context]) {
           [self release];
               return nil;
       }
// these should be in the class so that we can release them later,
// this will leak resources
GLuint framebuffer, renderbuffer;
// generate and bind a framebuffer
glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
// generate a colour renderbuffer; this example doesn't seem to want
// e.g. a depth buffer, but if it did then you'd generate and add one
// of those here also
// generate and bind
glGenRenderbuffersOES(1, &renderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, renderbuffer);
// get storage from the layer
[m_context
renderbufferStorage:GL_RENDERBUFFER_OES
fromDrawable: eaglLayer];
// link to the framebuffer
glFramebufferRenderbufferOES(
                            GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
                            GL_RENDERBUFFER_OES, renderbuffer);
glViewport(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
[self drawView];
}
return self;
}
Put framebuffer and renderbuffer somewhere you can get to them again at the relevant moment and you should also:
- (void)dealloc {
if(renderbuffer) glDeleteRenderbuffersOES(1, &renderbuffer);
if(framebuffer) glDeleteFramebuffersOES(1, &framebuffer);
if ([EAGLContext currentContext] == m_context) {
   [EAGLContext setCurrentContext:nil];
}
[m_context release];
[super dealloc];
}
I've tested this against the code you provide. I get the grey screen. Changing the call to glClearColor changes the colour of the screen, so clearly the GL context is working.
I ran into this issue and fixed it in my case by making sure the layer class was implemented right after the #implementation line.
#implementation GLView
+ (Class) layerClass
{
return [CAEAGLLayer class];
}
I got the gray background by getting rid of the line
m_window = [[UIWindow alloc] initWithFrame: screenBounds];
in application:didFinishLaunchingWithOptions: method in the file HelloArrowAppDelegate.h
The most likely cause is that you missed something when following the tutorial. Or they got it wrong. Whichever is most likely :-)
So the next stage is to debug and figure out what went wrong. Mostly likely you have missed a line of code which adds stuff to the display. I'd look in that section of your code first and compare it to the tutorial.
If that doesn't work then I'd take a copy of you code as a back up, then start stripping stuff out of it until you have the absolute minimal amount of code. Then post that here. Without some code we cannot tell you what is wrong.
whithout any code it might be difficult to tell you lol
your gray window comes from
(void) drawView
{
glClearColor(0.5f, 0.5f, 0.5f, 1);
glClear(GL_COLOR_BUFFER_BIT);
[m_context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
check that this is called correclty
I'd try add the following to your above code:
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CAEAGLLayer* eaglLayer = (CAEAGLLayer*) super.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
...
}
In code I use I define a drawableProperties but you seem to be missing it.