Basic Sky shell for iOS targets
R=abarth@chromium.org Review URL: https://codereview.chromium.org/1171573002.
This commit is contained in:
parent
b86de0a094
commit
6c7ef3c2da
3
engine/src/flutter/shell/ios/.gitignore
vendored
Normal file
3
engine/src/flutter/shell/ios/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.pbxproj
|
||||
*.xcworkspace
|
||||
*.xcodeproj
|
16
engine/src/flutter/shell/ios/Entitlements.xcent
Normal file
16
engine/src/flutter/shell/ios/Entitlements.xcent
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>application-identifier</key>
|
||||
<string>F5T262WGN6.com.google.sky</string>
|
||||
<key>com.apple.developer.team-identifier</key>
|
||||
<string>F5T262WGN6</string>
|
||||
<key>get-task-allow</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>F5T262WGN6.com.google.sky</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
82
engine/src/flutter/shell/ios/Info.plist
Normal file
82
engine/src/flutter/shell/ios/Info.plist
Normal file
@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
|
||||
<!--
|
||||
This executable name must match the name of the app provided to the
|
||||
ios_app GN template
|
||||
-->
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Sky</string>
|
||||
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.google.sky</string>
|
||||
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Sky</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
|
||||
<!--
|
||||
mojo:// URL handlers
|
||||
-->
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.google.mojo</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>mojo</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<!--
|
||||
Sky Load URL
|
||||
-->
|
||||
<key>com.google.sky.load_url</key>
|
||||
<string>https://domokit.github.io/sky_home</string>
|
||||
|
||||
<!--
|
||||
FIXME(csg): Xcode, as part of its build process, adds the following
|
||||
items to the Info.plist. It is not immediately clear if there is a
|
||||
command line utility that generates these. For now, just add the same
|
||||
manually
|
||||
-->
|
||||
<key>DTPlatformName</key>
|
||||
<string>iphonesimulator</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>iphonesimulator8.3</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.3</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>iPhoneSimulator</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
60
engine/src/flutter/shell/ios/main_ios.mm
Normal file
60
engine/src/flutter/shell/ios/main_ios.mm
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#include <asl.h>
|
||||
#import "sky_app_delegate.h"
|
||||
#include "base/at_exit.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "ui/gl/gl_surface.h"
|
||||
|
||||
static void InitializeLogging() {
|
||||
logging::LoggingSettings settings;
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
logging::InitLogging(settings);
|
||||
logging::SetLogItems(false, // Process ID
|
||||
false, // Thread ID
|
||||
false, // Timestamp
|
||||
false); // Tick count
|
||||
}
|
||||
|
||||
static void RedirectIOConnectionsToSyslog() {
|
||||
asl_log_descriptor(NULL, NULL, ASL_LEVEL_INFO, STDOUT_FILENO,
|
||||
ASL_LOG_DESCRIPTOR_WRITE);
|
||||
asl_log_descriptor(NULL, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO,
|
||||
ASL_LOG_DESCRIPTOR_WRITE);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
static void SkyDebuggerHookMain(void) {
|
||||
// By default, LLDB breaks way too early. This is before libraries have been
|
||||
// loaded and __attribute__((constructor)) methods have been called. In most
|
||||
// situations, this is unnecessary. Also, breakpoint resolution is not
|
||||
// immediate. So we provide this hook to break on.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifndef NDEBUG
|
||||
SkyDebuggerHookMain();
|
||||
#endif
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
base::AtExitManager exit_manager;
|
||||
RedirectIOConnectionsToSyslog();
|
||||
auto result = false;
|
||||
result = base::CommandLine::Init(0, nullptr);
|
||||
DLOG_ASSERT(result);
|
||||
InitializeLogging();
|
||||
result = base::i18n::InitializeICU();
|
||||
DLOG_ASSERT(result);
|
||||
result = gfx::GLSurface::InitializeOneOff();
|
||||
DLOG_ASSERT(result);
|
||||
return UIApplicationMain(argc, argv, nil,
|
||||
NSStringFromClass([SkyAppDelegate class]));
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "sky/engine/config.h"
|
||||
#include "sky/engine/wtf/Assertions.h"
|
||||
#include "sky/shell/service_provider.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/location.h"
|
||||
#include "mojo/public/cpp/application/service_provider_impl.h"
|
||||
#include "sky/services/ns_net/network_service_impl.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
// FIXME(csg): Put this in an application owned context
|
||||
base::LazyInstance<scoped_ptr<mojo::ServiceProviderImpl>> g_service_provider =
|
||||
LAZY_INSTANCE_INITIALIZER;
|
||||
base::LazyInstance<scoped_ptr<mojo::NetworkServiceFactory>>
|
||||
g_network_service_factory = LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
static void CreatePlatformServiceProvider(
|
||||
mojo::InterfaceRequest<mojo::ServiceProvider> request) {
|
||||
g_service_provider.Get().reset(new mojo::ServiceProviderImpl(request.Pass()));
|
||||
g_network_service_factory.Get().reset(new mojo::NetworkServiceFactory());
|
||||
g_service_provider.Get()->AddService(g_network_service_factory.Get().get());
|
||||
}
|
||||
|
||||
mojo::ServiceProviderPtr CreateServiceProvider(
|
||||
ServiceProviderContext* context) {
|
||||
DCHECK(context);
|
||||
mojo::MessagePipe pipe;
|
||||
auto request = mojo::MakeRequest<mojo::ServiceProvider>(pipe.handle1.Pass());
|
||||
context->platform_task_runner->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(CreatePlatformServiceProvider, base::Passed(request.Pass())));
|
||||
return mojo::MakeProxy(
|
||||
mojo::InterfacePtrInfo<mojo::ServiceProvider>(pipe.handle0.Pass(), 0u));
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
25
engine/src/flutter/shell/ios/platform_view_ios.h
Normal file
25
engine/src/flutter/shell/ios/platform_view_ios.h
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SKY_SHELL_PLATFORM_VIEW_IOS_H_
|
||||
#define SKY_SHELL_PLATFORM_VIEW_IOS_H_
|
||||
|
||||
#include "sky/shell/platform_view.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
class PlatformViewIOS : public PlatformView {
|
||||
public:
|
||||
void SurfaceCreated(gfx::AcceleratedWidget widget);
|
||||
void SurfaceDestroyed(void);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(PlatformViewIOS);
|
||||
};
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
#endif // SKY_SHELL_PLATFORM_VIEW_IOS_H_
|
23
engine/src/flutter/shell/ios/platform_view_ios.mm
Normal file
23
engine/src/flutter/shell/ios/platform_view_ios.mm
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "platform_view_ios.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
void PlatformViewIOS::SurfaceCreated(gfx::AcceleratedWidget widget) {
|
||||
DCHECK(window_ == 0);
|
||||
window_ = widget;
|
||||
SurfaceWasCreated();
|
||||
}
|
||||
|
||||
void PlatformViewIOS::SurfaceDestroyed() {
|
||||
DCHECK(window_);
|
||||
window_ = 0;
|
||||
SurfaceWasDestroyed();
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
11
engine/src/flutter/shell/ios/sky_app_delegate.h
Normal file
11
engine/src/flutter/shell/ios/sky_app_delegate.h
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SkyAppDelegate : UIResponder<UIApplicationDelegate>
|
||||
|
||||
@property(strong, nonatomic) UIWindow* window;
|
||||
|
||||
@end
|
53
engine/src/flutter/shell/ios/sky_app_delegate.mm
Normal file
53
engine/src/flutter/shell/ios/sky_app_delegate.mm
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "sky_app_delegate.h"
|
||||
#import "sky_view_controller.h"
|
||||
|
||||
#include "sky/shell/shell.h"
|
||||
#include "sky/shell/service_provider.h"
|
||||
#include "sky/shell/ui_delegate.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
|
||||
@implementation SkyAppDelegate {
|
||||
base::LazyInstance<scoped_ptr<base::MessageLoop>> _main_message_loop;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication*)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
|
||||
[self setupSkyShell];
|
||||
[self setupViewport];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)setupSkyShell {
|
||||
[self adoptPlatformRunLoop];
|
||||
|
||||
auto service_provider_context =
|
||||
make_scoped_ptr(new sky::shell::ServiceProviderContext(
|
||||
_main_message_loop.Get()->task_runner()));
|
||||
sky::shell::Shell::Init(service_provider_context.Pass());
|
||||
}
|
||||
|
||||
- (void)adoptPlatformRunLoop {
|
||||
_main_message_loop.Get().reset(new base::MessageLoopForUI);
|
||||
// One cannot start the message loop on the platform main thread. Instead,
|
||||
// we attach to the CFRunLoop
|
||||
base::MessageLoopForUI::current()->Attach();
|
||||
}
|
||||
|
||||
- (void)setupViewport {
|
||||
CGRect frame = [UIScreen mainScreen].bounds;
|
||||
UIWindow* window = [[UIWindow alloc] initWithFrame:frame];
|
||||
SkyViewController* viewController = [[SkyViewController alloc] init];
|
||||
window.rootViewController = viewController;
|
||||
[viewController release];
|
||||
self.window = window;
|
||||
[window release];
|
||||
[self.window makeKeyAndVisible];
|
||||
}
|
||||
|
||||
@end
|
9
engine/src/flutter/shell/ios/sky_surface.h
Normal file
9
engine/src/flutter/shell/ios/sky_surface.h
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SkySurface : UIView
|
||||
|
||||
@end
|
162
engine/src/flutter/shell/ios/sky_surface.mm
Normal file
162
engine/src/flutter/shell/ios/sky_surface.mm
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "sky_surface.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <OpenGLES/EAGLDrawable.h>
|
||||
|
||||
#include "sky/shell/ui_delegate.h"
|
||||
#include "sky/shell/shell.h"
|
||||
#include "sky/shell/ios/platform_view_ios.h"
|
||||
|
||||
#include "mojo/public/cpp/bindings/interface_request.h"
|
||||
#include "sky/services/viewport/input_event.mojom.h"
|
||||
#include "base/time/time.h"
|
||||
|
||||
static inline sky::EventType EventTypeFromUITouchPhase(UITouchPhase phase) {
|
||||
switch (phase) {
|
||||
case UITouchPhaseBegan:
|
||||
return sky::EVENT_TYPE_POINTER_DOWN;
|
||||
case UITouchPhaseMoved:
|
||||
case UITouchPhaseStationary:
|
||||
// There is no EVENT_TYPE_POINTER_STATIONARY. So we just pass a move type
|
||||
// with the same coordinates
|
||||
return sky::EVENT_TYPE_POINTER_MOVE;
|
||||
case UITouchPhaseEnded:
|
||||
return sky::EVENT_TYPE_POINTER_UP;
|
||||
case UITouchPhaseCancelled:
|
||||
return sky::EVENT_TYPE_POINTER_CANCEL;
|
||||
}
|
||||
|
||||
return sky::EVENT_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
@implementation SkySurface {
|
||||
BOOL _platformViewInitialized;
|
||||
|
||||
sky::ViewportObserverPtr _viewport_observer;
|
||||
}
|
||||
|
||||
- (gfx::AcceleratedWidget)acceleratedWidget {
|
||||
return (gfx::AcceleratedWidget)self.layer;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
|
||||
[self configureLayerDefaults];
|
||||
|
||||
[self setupPlatformViewIfNecessary];
|
||||
|
||||
CGSize size = self.bounds.size;
|
||||
CGFloat scale = [UIScreen mainScreen].scale;
|
||||
|
||||
_viewport_observer->OnViewportMetricsChanged(size.width * scale,
|
||||
size.height * scale, scale);
|
||||
}
|
||||
|
||||
- (void)configureLayerDefaults {
|
||||
CAEAGLLayer* layer = reinterpret_cast<CAEAGLLayer*>(self.layer);
|
||||
layer.allowsGroupOpacity = YES;
|
||||
layer.opaque = YES;
|
||||
CGFloat screenScale = [UIScreen mainScreen].scale;
|
||||
layer.contentsScale = screenScale;
|
||||
// Note: shouldRasterize is still NO. This is just a defensive measure
|
||||
layer.rasterizationScale = screenScale;
|
||||
}
|
||||
|
||||
- (void)setupPlatformViewIfNecessary {
|
||||
if (_platformViewInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
_platformViewInitialized = YES;
|
||||
|
||||
[self notifySurfaceCreation];
|
||||
[self connectToViewportObserverAndLoad];
|
||||
}
|
||||
|
||||
- (sky::shell::PlatformViewIOS*)platformView {
|
||||
auto view = static_cast<sky::shell::PlatformViewIOS*>(
|
||||
sky::shell::Shell::Shared().view());
|
||||
DCHECK(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
- (void)notifySurfaceCreation {
|
||||
self.platformView->SurfaceCreated(self.acceleratedWidget);
|
||||
}
|
||||
|
||||
- (NSString*)skyInitialLoadURL {
|
||||
return [NSBundle mainBundle].infoDictionary[@"com.google.sky.load_url"];
|
||||
}
|
||||
|
||||
- (void)connectToViewportObserverAndLoad {
|
||||
auto view = sky::shell::Shell::Shared().view();
|
||||
auto interface_request = mojo::GetProxy(&_viewport_observer);
|
||||
view->ConnectToViewportObserver(interface_request.Pass());
|
||||
|
||||
mojo::String string(self.skyInitialLoadURL.UTF8String);
|
||||
_viewport_observer->LoadURL(string);
|
||||
}
|
||||
|
||||
- (void)notifySurfaceDestruction {
|
||||
self.platformView->SurfaceDestroyed();
|
||||
}
|
||||
|
||||
#pragma mark - UIResponder overrides for raw touches
|
||||
|
||||
- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase {
|
||||
auto eventType = EventTypeFromUITouchPhase(phase);
|
||||
const CGFloat scale = [UIScreen mainScreen].scale;
|
||||
|
||||
for (UITouch* touch in touches) {
|
||||
auto input = sky::InputEvent::New();
|
||||
input->type = eventType;
|
||||
|
||||
auto timedelta = base::TimeDelta::FromSecondsD(touch.timestamp);
|
||||
input->time_stamp = timedelta.InMilliseconds();
|
||||
|
||||
input->pointer_data = sky::PointerData::New();
|
||||
input->pointer_data->kind = sky::POINTER_KIND_TOUCH;
|
||||
|
||||
CGPoint windowCoordinates = [touch locationInView:nil];
|
||||
|
||||
input->pointer_data->x = windowCoordinates.x * scale;
|
||||
input->pointer_data->y = windowCoordinates.y * scale;
|
||||
|
||||
_viewport_observer->OnInputEvent(input.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
[self dispatchTouches:touches phase:UITouchPhaseBegan];
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
[self dispatchTouches:touches phase:UITouchPhaseMoved];
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
[self dispatchTouches:touches phase:UITouchPhaseEnded];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
|
||||
[self dispatchTouches:touches phase:UITouchPhaseCancelled];
|
||||
}
|
||||
|
||||
#pragma mark - Misc.
|
||||
|
||||
+ (Class)layerClass {
|
||||
return [CAEAGLLayer class];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self notifySurfaceDestruction];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
9
engine/src/flutter/shell/ios/sky_view_controller.h
Normal file
9
engine/src/flutter/shell/ios/sky_view_controller.h
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SkyViewController : UIViewController
|
||||
|
||||
@end
|
24
engine/src/flutter/shell/ios/sky_view_controller.mm
Normal file
24
engine/src/flutter/shell/ios/sky_view_controller.mm
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "sky_view_controller.h"
|
||||
#import "sky_surface.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@implementation SkyViewController
|
||||
|
||||
- (void)loadView {
|
||||
SkySurface* surface = [[SkySurface alloc] init];
|
||||
|
||||
surface.autoresizingMask =
|
||||
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
|
||||
self.view = surface;
|
||||
|
||||
[surface release];
|
||||
}
|
||||
|
||||
@end
|
Loading…
x
Reference in New Issue
Block a user