Objective-C 程序设计语言采用特定的语法,来定义类和方法、调用对象的方法、动态地扩展类,以及创建编程接口,来解决具体问题。Objective-C 作为 C 程序设计语言的超集,支持与 C 相同的基本语法。有C#语言的编程经验,那么Objective-C将更容易上手,本文将从各个方面对比C#与Objective-C的语法。
class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: true; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;">C#: string name = “lwme.cnblogs.com”; Objective-C: NSString *name = @”lwme.cnblogs.com”;
字符串前面的@符号是objc在标准C语言基础上添加的特性,"SteveZ"前面有一个@符号表示字符串应该作为Cocoa的NSString来处理,是把C string转换成NSString的一个简写。
C#: name.Length Objective-C: [name length] name.length
C#: int i = 10; string age = i.ToString(); int intAge = int.Parse(age); Objective-C: NSInteger i = 10; NSString *age = [@(i) stringValue]; // 转换成NSNumber再获取字符串值 NSString *age = [NSString stringWithFormat:@"%d", i]; NSInteger intAge = [age integerValue];
C#: string host = "lwme" + ".cnblogs.com"; Objective-C: NSString *host = @"lwme" @".cnblogs.com" NSString *host = [@"lwme" stringByAppendingString:@".cnblogs.com"]; NSString *host = [NSString stringWithFormat:@"%@%@", @"lwme", @".cnblogs.com"];
C#: bool isEqual = strA == strB; bool isEqual = string.Compare(strA, strB, true) == 0; // 忽略大小写 bool isEqual = string.Compare(strA, strB, StringComparison.InvariantCultureIgnoreCase) == 0; bool isStartWith = strA.StartsWith(strB); bool isStartWith = strA.StartsWith(strB, StringComparison.InvariantCultureIgnoreCase); bool isEndWith = strA.EndsWith(strB); bool isEndWith = strA.EndsWith(strB, StringComparison.InvariantCultureIgnoreCase); bool isContain = strA.Contains(strB); bool isContain = strA.Contains(strB, StringComparison.InvariantCultureIgnoreCase); Objective-C: BOOL isEqual = [strA isEqualToString: strB]; BOOL isEqual = [strA caseInsensitiveCompare:strB] == NSOrderedSame; // 忽略大小写 BOOL isEqual = [strA compare:strB options:NSCaseInsensitiveSearch] == NSOrderedSame; BOOL isStartWith = [strA hasPrefix:strB]; BOOL isEndWith = [strA hasSuffix:strB]; BOOL isContain = [strA rangeOfString:strB].location != NSNotFound; BOOL isContain = [strA rangeOfString:strB options:NSCaseInsensitiveSearch].location != NSNotFound;
C#: bool empty = string.IsNullOrEmpty(value); bool empty = string.IsNullOrWhiteSpace(value); Objective-C: BOOL empty = (value == nil || value.length == 0); BOOL empty = (value == nil || value.length == 0 || [[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0); // 同IsNullOrWhiteSpace
C#: string name = value.ToLower(); string name = value.ToUpper(); Objective-C: NSString *name = [value lowercasestring]; NSString *name = [value uppercasestring];
C#: float x = 2.43534f; string s = x.ToString(“n2″); string s = string.Format("{0} {1}", "lwme", "cnblogs"); Objective-C: float x = 2.34454f; NSString *s = [NSString stringWithFormat: @"%.2f", x]; NSString *s = [NSString stringWithFormat: @"%@ %@", @"lwme", @"cnblogs"];
objc和C#一样,字符串都是不可变的,要改变字符串则分别需要使用StringBuilder、NSMutableString。
C#: StringBuilder builder = new StringBuilder(20); builder.Append("lwme"); builder.AppendFormat(".{0}.{1}", "cnblogs", "com"); Objective-C: NSMutableString *builder = [NSMutableString stringWithCapacity:20]; [builder appendString:@"lwme"]; [builder appendFormat:@".%@.%@", @"cnblogs", @"com"];
C#: string[] data = {}; string[] data = {"one", "two"}; Objective-C: // 旧语法 NSArray* data = [NSArray arrayWithObjects:@"one", @"two", nil]; // (定义数组时用逗号分隔对象列表,并且必须以nil结尾) // objc 2.0新语法 NSArray *data = @[]; //空数组 NSArray* data = @[@"one", @"two"];
C#: data.Length Objective-C: [data count] data.count
C#: data[0] data[0]="two"; Objective-C: [data objectAtIndex:0] data[0] // objc 2.0 新语法 data[0]=@"two";
C#: int index = data.IndexOf("one"); Objective-C: int index = [data indexOfObject:@"one"];
C#: foreach (string item in array) ... Objective-C: for (NSString *item in array) ...
objc和C#一样,数组是不可变的,如果需要改变数组的元素,则分别要用到List<T>、NSMutableArray。
C#: List<string> list = new List<string>(); List<string> list = new List<string>(20); List<string> list = new List<string> { "lwme", "cnblogs" }; list.Add("lwme"); list.AddRange(new[] { "l", "w", "m", "e" }); list.Insert(0, "lwme"); list.Remove("lwme"); list.RemoveAt(0); list.Clear(); bool isContain = list.Contains("lwme"); bool isContain = list.Contains("lwme", StringComparer.InvariantCultureIgnoreCase); Objective-C: NSMutableArray *list = [NSMutableArray array]; NSMutableArray *list = [NSMutableArray arrayWithCapcity: 20]; NSMutableArray *list = [@[@"lwme", @"cnblogs"] mutableCopy]; [list addObject:@"lwme"]; [list addObjectsFromArray:@[@"lwme, @"cnblogs"]]; [list insertObject:@"lwme", atIndex:0]; [list removeObject:@"lwme"]; [list removeObjectAtIndex:0]; [list removeAllObjects]; BOOL isContain = [list containsObject:@"lwme"];
在objc中有不可变的字典NSDictionary,在C#中没有对应的,而可变的字典NSMutableDictionary对应C#中的Dictionary<TKey,TValue>。
C#: Dictionary<string, string> dict = new Dictionary<string, string>(); Dictionary<string, string> dict = new Dictionary<string, string>(20); Dictionary<string, string> dict = new Dictionary<string, string> { {"name", "lwme"}, {"host", "cnblogs"} }; dict.Add("name", "lwme"); dict["name"] = "lwme"; dict.Remove("name"); dict.Clear(); dict.ContainsKey("name"); string name = dict["name"]; // dict.TryGetValue("name", out ...) Objective-C: NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"lwme", 0, @"cnblogs", 1, nil]; // 旧语法 NSDictionary *dict = @{0: @"lwme", 1: @"cnblogs"}; // objc2.0语法 NSMutableDictionary *dict = [NSMutableDictionary dictionary]; NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 20]; NSMutableDictionary *dict = [@{0: @"lwme", 1: @"cnblogs"} mutableCopy]; [dict setObject:@"lwme" forKey:@"name"]; [dict removeObjectForKey:@"name"]; [dict removeAllObjects]; BOOL isContain = [[dict allKeys] containsObject:@"name"]; BOOL isContain = [dict objectForKey:@"name"] != nil; NSString *name = [dict objectForKey:@"name"]; NSString *name = dict[@"name"];
objc中有c语言的基本类型如int、float、struct等,还有它们的封装类型NSNumber,由于NSNumber只能存储对象,不能存储任何基本类型,所以这些基本类型需要用NSNumber来包装。
C#: int ii = 1; long li = 1; float fi = 1.1; double di = 1.1; bool b = true; Objective-C: int ii = 1; long li = 1; float fi = 1.1; double di = 1.1; bool b = true; BOOL b = YES; NSNumber ii = [NSNumber numberWithInt: 1]; NSNumber li = [NSNumber numberWithLong: 1]; NSNumber fi = [NSNumber numberWithFloat: 1.1]; NSNumber di = [NSNumber numberWithDouble: 1.1]; NSNumber b = [NSNumber numberWithBOOL: YES]; NSNumber ii = @1; NSNumber li = @1; NSNumber fi = @1.1; NSNumber di = @1.1; NSNumber b = @YES;
objc的类分成.h头文件和.m实现文件,.h头文件里定义所有公开的方法、属性、字段,.m实现文件里实现公开的方法以及私有的字段、方法。
C#: public class Person { private int privateField; public int Age {get;set;} public string FirstName {get;set;} public string LastName {get;set;} public Person(int age) { this.Age = age; this.OnAgeChange(age); } private void OnAgeChange(int age) { } public string GetFullName() { return this.FirstName + " " + this.LastName; } public void SetFullName(string firstName, string lastName) { this.FirstName = firstName; this.LastName = lastName; } public virtual void PrintAge(){ Console.WriteLine("{0}", this.Age); } public static Person CreatePerson(int age) { return new Person(age); } } Objective-C: Person.h: @interface Person : NSObject -(id)initWithAge:(int)age; // 构造器 @property(nonatomic) int age; // 属性 @property(nonatomic) NSString *firstName; @property(nonatomic) NSString *lastName; -(NSString*)getFullName; // 方法 -(void)setFullName:(NSString *)firstName andLastName:(NSString *)lastName; -(void)printAge; +(id)createPersonWithAge:(int)age; @end Person.m: @interface Person() { int _privateField; // 私有字段 } @end @implementation Person @synthesize age, firstName, lastName; -(id)initWithAge:(int)age { if(self = [super init]) { self.age = age; [self onAgeChange:age]; } return self; } -(void)onAgeChange:(int)age { } -(NSString*)getFullName { return [NSString stringWithFormat:"%@ %@", self.firstName, self.lastName]; } -(void)setFullName:(NSString *)firstName andLastName:(NSString *)lastName { self.firstName = firstName; self.lastName = lastName; } -(void)printAge { NSLog(@"%i", self.age); } +(id)createPersonWithAge:(int)age { return [[Person alloc] initWithAge:age]; } @end
C#: Person p = new Person(11); Person p = Person.CreatePerson(11); p.setFullName("lwme", "cnblogs"); p.FirstName = "lwme"; p.PrintAge(); string fullName = p.GetFullName(); int age = p.Age; Objective-C: Person *p = [[Person alloc] initWithAge:11]; Person *p = [Person CreateWithAge:11]; [p setFullName:@"lwme" andLastName:@"cnblogs"]; p.firstName = @"lwme"; [p PrintAge]; NSString *fullName = [p getFullName]; int age = p.Age;
C#: public class ChildPerson: Person { public ChildPerson(int age): base(age){} public override void PrintAge() { base.PrintAge(); Console.WriteLine("print age in childperson"); } } Objective-C: ChildPerson.h @interface ChildPerson:Person @end ChildPerson.m @interface ChildPerson() @end @implementation ChildPerson -(void)printAge { [super printAge]; NSLog(@"print age in childperson"); } @end
C#: ChildPerson p = new ChildPerson(11); string val = p.ToString(); Objective-C: ChildPerson *p = [[ChildPerson alloc] initWithAge:11]; NSString *val = [p description];
objc中的协议可以对应C#中的接口、事件,其中事件一般声明为delegate名称的属性,在使用的时候只需要设置delete就可以绑定所有事件。
C# public interface IEquatable<T> { bool Equals(T obj); } public class Person : IEquatable<MyClass> { public Action<Person> onAgeChanged; public int Age { get; set; } public bool Equals(Person p) { return p.Age == this.Age; } public void SetAge(int age) { this.Age = age; if (onAgeChanged != null) onAgeChanged(this); } } Objective-C @protocol IEquatable @required -(bool)equals: (Person*)obj; @end @protocol IChangeAction @optional -(void)onAgeChange: (Person*)obj; @end @interface Person : NSObject<IEquatable> @property(nonatomic) int age; @property(nonatomic, weak)id<IChangeAction> delegate; -(void)setAge:(int)age; @end @implementation Person @synthesize age; -(bool)equals:(Person*)p { return p.age == self.age; } -(void)setAge:(int)age { self.age = age; if ([self.delegate respondsToSelector:@selector(onAgeChange:)]) [self.delegate onAgeChange:self]; } @end
C# public enum Orientation: uint { Vertical = 0, Horizontal = 1 } Objective-C typedef enum Orientation : NSUInteger { OrientationVertical = 0, OrientationHorizontal = 1 } Orientation;
C# public Orientation TextAlignment {get;set} // 属性 label.TextAlignment = Orientation.Horizontal; Objective-C @property(nonatomic, assign) Orientation textAlignment; label.textAlignment = OrientationHorizontal;
C#: Type t = typeof(Person); Objective-C: Class c = [Person class];
C#: Person p = new Person(); Type t = p.GetType(); Objective-C: Person *p = [[Person alloc] init]; Class c = p.class;
C#: string name = type.Name; string name = typeof(Person).Name; Objective-C: NSString *name = NSStringFromClass(p.class); NSString *name = NSStringFromClass([Person class]);
C#: bool isPerson = p is Person; Objective-C: BOOL isPerson = [p isKindOfClass:c];
C#: bool isInherited = p is Person; bool isInherited = p.GetType().IsSubclassOf(typeof(Person)); bool isInherited = typeof(ChildPerson).IsSubclassOf(typeof(Person)); bool isInherited = typeof(Person).IsAssignableFrom(typeof(ChildPerson)); Objective-C: BOOL isInherited = [[p class] isSubclassOfClass:[Person class]]; BOOL isInherited = [[ChildPerson class] isSubclassOfClass:[Person class]];
C#: bool isImplemented = p is IEquatable; bool isImplemented = typeof(IEquatable<>).IsAssignableFrom(p.GetType()); bool isImplemented = typeof(IEquatable<>).IsAssignableFrom(typeof(Person)); bool isImplemented = typeof(Person).GetInterfaces().Contains(typeof(IEquatable<>)); Objective-C: BOOL isImplemented = [p class conformsToProtocol:@protocol(IEquaatable)];
C#: object instance = Activator.CreateInstance(Type.GetType("ChildPerson")); Objective-C: id instance = [[NSClassFromString("ChildPerson") alloc] init];
C#: MethodInfo method = type.GetMethod("PrintAge"); bool hasMethod = method != null; method.Invoke(p, null); Objective-C: SEL method = @selector(printAge); BOOL hasMethod = [p respondsToSelector: method]; [p performSelector:method];
C#: object age = p.GetType().GetProperty(“Age”).GetValue(p, null); foreach(PropertyInfo pi in typeof(Person).GetProperties()) { // pi.Name } Objective-C: id age = [p valueForKey:@"Age"]; unsigned int propertyCount = 0; objc_property_t * properties = class_copyPropertyList([Person class], &propertyCount); for (unsigned int i = 0; i < propertyCount; ++i) { objc_property_t property = properties[i]; const char * name = property_getName(property); } free(properties);
objc里的Category可以很好的实现C#中的扩展方法。
C# public static class PersonExtension { public static void PrintFullName(this Person p) { Console.WriteLine(p.GetFullName()); } } Objective-C Person+PrintExtension.h #import "Person.h" @interface Person (PrintExtension) -(void)PrintFullName; @end Person+PrintExtension.m @implementation Person (PrintExtension) -(void)PrintFullName { NSLog(@"%@", [self getFullName]); } @end
C# try { } catch (Exception ex) { } finally { } Objective-C @try { } @catch (NSException *exception) { } @finally { }
objc没有命名空间机制,直接从包或者当前项目引入头文件即可。
C# using System; using System.Text; using MyCompany.CustomNamespace; Objective-C #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #import "CustomClass.h"
objc中有ARC机制对应.net 中的GC,详细的可以看:http://snakcakeblog.tumblr.com/post/47765862590/grudge-match-c-gc-vs-objective-c-arc
在C#当中,源代码一般被编译成程序集,而在objc中,都是编译成静态链接库,而且引用方式也不相同。
http://www.infragistics.com/community/blogs/stevez/archive/2013/05/09/c-to-objective-c-the-ultimate-guide.aspx(本文内容主要来自它,并做了一些更改)
http://developer.apple.com/library/ios/#referencelibrary/GettingStarted/RoadMapiOSCh/chapters/Introduction.html
http://www.anotherchris.net/csharp/objective-c-by-example-for-a-csharp-developer/
http://www.cnblogs.com/chijianqiang/archive/2012/06/22/objc-category-protocol.html
http://www.techotopia.com/index.php/Working_with_String_Objects_in_Objective-C
http://overooped.com/post/41803252527/methods-of-concurrency