Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added non KVO dependent iOS specific, extendable ICreatesObservable…
…ForProperty implementation supporting some core UIKit controls - Added MonoTouch Linker XML definition file that should be added to MonoTouch projects in release configuration. Otherwise the Monotouch Linker might optimize away properties referenced soley through ReactiveUI (reflection-driven) data-binding
- Loading branch information
Oliver Weichhold
committed
May 25, 2013
1 parent
c948458
commit e4590ab
Showing
6 changed files
with
237 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<linker> | ||
<assembly fullname="monotouch"> | ||
<type fullname="MonoTouch.UIKit.UIControl" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITextField" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITextView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UILabel" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UISlider" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UISearchBar" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIButton" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITableView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIActionSheet" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIDatePicker" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIProgressView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UISwitch" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIActivityIndicatorView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIAlertView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIBarButtonItem" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIBarItem" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UICollectionView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIScrollView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIImage" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIImageView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UINavigationBar" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UINavigationItem" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIPageControl" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIPickerView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIRefreshControl" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UISegmentedControl" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIStepper" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITabBar" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITabBarItem" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITableViewCell" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIToolbar" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UITouch" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIWebView" preserve="properties"></type> | ||
<type fullname="MonoTouch.UIKit.UIWindow" preserve="properties"></type> | ||
</assembly> | ||
</linker> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System; | ||
using ReactiveUI; | ||
using System.Collections.Generic; | ||
using MonoTouch.UIKit; | ||
using System.Linq; | ||
using MonoTouch.Foundation; | ||
using System.Reactive.Linq; | ||
using System.Runtime.InteropServices; | ||
using System.Reactive.Disposables; | ||
|
||
namespace ReactiveUI.Cocoa | ||
{ | ||
public class UIKitObservableForProperty : UIKitObservableForPropertyBase | ||
{ | ||
public UIKitObservableForProperty () | ||
{ | ||
Register(typeof(UIControl), "Value", 9, (s, p)=> ObservableFromUIControlEvent(s, p, UIControlEvent.ValueChanged)); | ||
|
||
Register(typeof(UITextField), "Text", 10, (s, p) => ObservableFromNotification(s, p, UITextField.TextFieldTextDidChangeNotification)); | ||
|
||
Register(typeof(UIDatePicker), "Date",10, (s, p)=> ObservableFromUIControlEvent(s, p, UIControlEvent.ValueChanged)); | ||
|
||
Register(typeof(UISegmentedControl), "SelectedSegment", 10, (s, p)=> ObservableFromUIControlEvent(s, p, UIControlEvent.ValueChanged)); | ||
|
||
Register(typeof(UISwitch), "On", 10, (s, p)=> ObservableFromUIControlEvent(s, p, UIControlEvent.ValueChanged)); | ||
|
||
Register(typeof(UISegmentedControl), "SelectedSegment", 10, (s, p)=> ObservableFromUIControlEvent(s, p, UIControlEvent.ValueChanged)); | ||
|
||
// Warning: This will stomp the Control's delegate | ||
Register(typeof(UITabBar), "SelectedItem", 10, (s, p) => ObservableFromEvent(s, p, "ItemSelected")); | ||
|
||
// Warning: This will stomp the Control's delegate | ||
Register(typeof(UISearchBar), "Text", 10, (s, p) => ObservableFromEvent(s, p, "TextChanged")); | ||
} | ||
} | ||
} | ||
|
155 changes: 155 additions & 0 deletions
155
ReactiveUI.Platforms/Cocoa/UIKitObservableForPropertyBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
using System; | ||
using ReactiveUI; | ||
using MonoTouch.Foundation; | ||
using MonoTouch.UIKit; | ||
using System.Reactive.Disposables; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reactive.Linq; | ||
|
||
namespace ReactiveUI.Cocoa | ||
{ | ||
public abstract class UIKitObservableForPropertyBase : | ||
ICreatesObservableForProperty | ||
{ | ||
#region ICreatesObservableForProperty implementation | ||
|
||
public int GetAffinityForObject(Type type, bool beforeChanged = false) | ||
{ | ||
if(beforeChanged) | ||
return 0; | ||
|
||
var info = config.Keys | ||
.Where(x=> x.IsAssignableFrom(type)) | ||
.Where(x=> config[x].Values.Any()) | ||
.Select(x=> config[x].Values.OrderByDescending(y=> y.Affinity).FirstOrDefault()) | ||
.OrderByDescending(x=> x.Affinity) | ||
.FirstOrDefault(); | ||
|
||
if(info == null) | ||
return 0; | ||
|
||
return info.Affinity; | ||
} | ||
|
||
public IObservable<IObservedChange<object, object>> GetNotificationForProperty(object sender, string propertyName, bool beforeChanged = false) | ||
{ | ||
var type = sender.GetType(); | ||
|
||
if(beforeChanged) | ||
return Observable.Never<IObservedChange<object, object>>(); | ||
|
||
Dictionary<string, ObservablePropertyInfo> typeProperties; | ||
if(!config.TryGetValue(type, out typeProperties)) | ||
throw new NotSupportedException(string.Format("Notifications for {0} are not supported", type.Name)); | ||
|
||
ObservablePropertyInfo info; | ||
if(!typeProperties.TryGetValue(propertyName, out info)) | ||
throw new NotSupportedException(string.Format("Notifications for {0}.{1} are not supported", type.Name, propertyName)); | ||
|
||
return info.CreateObservable((NSObject) sender, propertyName); | ||
} | ||
|
||
#endregion | ||
|
||
internal class ObservablePropertyInfo | ||
{ | ||
public int Affinity; | ||
public Func<NSObject, string, IObservable<IObservedChange<object, object>>> CreateObservable; | ||
} | ||
|
||
/// <summary> | ||
/// Configuration map | ||
/// </summary> | ||
readonly Dictionary<Type, Dictionary<string, ObservablePropertyInfo>> config = | ||
new Dictionary<Type, Dictionary<string, ObservablePropertyInfo>>(); | ||
|
||
/// <summary> | ||
/// Registers an observable factory for the specified type and property. | ||
/// </summary> | ||
/// <param name="type">Type.</param> | ||
/// <param name="property">Property.</param> | ||
/// <param name="createObservable">Create observable.</param> | ||
protected void Register(Type type, string property, int affinity, Func<NSObject, string, IObservable<IObservedChange<object, object>>> createObservable) | ||
{ | ||
Dictionary<string, ObservablePropertyInfo> typeProperties; | ||
if(!config.TryGetValue(type, out typeProperties)) | ||
{ | ||
typeProperties = new Dictionary<string, ObservablePropertyInfo>(); | ||
config[type] = typeProperties; | ||
} | ||
|
||
var info = new ObservablePropertyInfo { Affinity = affinity, CreateObservable = createObservable }; | ||
typeProperties[property] = info; | ||
} | ||
|
||
/// <summary> | ||
/// Creates an Observable for a UIControl Event | ||
/// </summary> | ||
/// <returns>An observable</returns> | ||
/// <param name="sender">The sender</param> | ||
/// <param name="propertyName">The property name </param> | ||
/// <param name="evt">The control event to listen for</param> | ||
protected static IObservable<IObservedChange<object, object>> ObservableFromUIControlEvent(NSObject sender, string propertyName, UIControlEvent evt) | ||
{ | ||
return Observable.Create<IObservedChange<object, object>>(subj => | ||
{ | ||
var control = (UIControl) sender; | ||
EventHandler handler = (s,e)=> | ||
{ | ||
subj.OnNext(new ObservedChange<object, object>() { Sender = sender, PropertyName = propertyName }); | ||
}; | ||
control.AddTarget(handler, evt); | ||
return Disposable.Create(() => | ||
{ | ||
control.RemoveTarget(handler, evt); | ||
}); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Creates an Observable for a NSNotificationCenter notification | ||
/// </summary> | ||
/// <returns>The from notification.</returns> | ||
/// <param name="sender">Sender.</param> | ||
/// <param name="propertyName">Property name.</param> | ||
/// <param name="notification">Notification.</param> | ||
protected static IObservable<IObservedChange<object, object>> ObservableFromNotification(NSObject sender, string propertyName, NSString notification) | ||
{ | ||
return Observable.Create<IObservedChange<object, object>>(subj => | ||
{ | ||
var handle = NSNotificationCenter.DefaultCenter.AddObserver (notification, (e)=> | ||
{ | ||
subj.OnNext(new ObservedChange<object, object>() { Sender = sender, PropertyName = propertyName }); | ||
}, sender); | ||
return Disposable.Create(() => | ||
{ | ||
NSNotificationCenter.DefaultCenter.RemoveObserver(handle); | ||
}); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Creates an Observable for a NSNotificationCenter notification | ||
/// </summary> | ||
/// <returns>The from notification.</returns> | ||
/// <param name="sender">Sender.</param> | ||
/// <param name="propertyName">Property name.</param> | ||
/// <param name="notification">Notification.</param> | ||
protected static IObservable<IObservedChange<object, object>> ObservableFromEvent(NSObject sender, string propertyName, string eventName) | ||
{ | ||
return Observable.Create<IObservedChange<object, object>>(subj => | ||
{ | ||
return Observable.FromEventPattern(sender, eventName).Subscribe((e) => | ||
{ | ||
subj.OnNext(new ObservedChange<object, object>() { Sender = sender, PropertyName = propertyName }); | ||
}); | ||
}); | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters