Leon force这款游戏只能IOS系统按f1才能进入系统玩?

ios可以玩荒野行动国际服吗 咋下载?_百度知道
ios可以玩荒野行动国际服吗 咋下载?
我有更好的答案
苹果 设置-通用-语言地区改成美国 然后再开游戏里面语言选中文,里面有两个区第一个是美服(需要创建新角色)第二个是国际服不用创建角色。祝你玩的愉快。
龙&马,咹全、热闹。因为目前多数的智能手机在听筒旁边安装了距离感应器,当你打电话,脸靠近时,手机的屏幕是会自动熄灭的,而你的手机远离脸部时,手机屏幕又会重新亮了,这是节省你手机的电量,增长你使用手机的时间。正常情况下打电话,用手遮住屏幕上方,手机屏幕就会自动暗了,拿开手,屏幕又会亮起来。因此:1)黑屏的原因可能是保护膜或者什么东西遮住了距离感应器。可以用手指遮住手机左上角的感光器,然后放开,如果成功,则是这个毛病。2)距离感应器有故障了。需要更换。软件的原因:可能在设置里,感应器设置不当,可以到手机的设置下的“显示”下的,感应器校验项目,校验一下可能会回复正常。不能挂电话:到设置下面,选择电源键按下时挂断电话。
你也可以到买PSP的地方去装,省的下载费工夫。来看:我的战神就是在这儿下的
电玩巴士:下载速度有点慢,但是比较全
psp游民星空:主要是游戏攻略及资料
/Soft/tvgame/psp/多玩:值得信赖的网站
psp/down/电驴:必须用电驴软件下
迅雷:不值得期待的网站!
├[Passport_To_Amsterdam][阿姆斯特丹护照][ISO][欧版]
├[ACTIVISION经典游戏合集][美版]
├[爱的急救箱][欧版]B:
├[不可思议的游戏玄武开传外传镜之巫女][日版]
├[哔波猴学苑2亲亲猜拳玩猴戏][ISO][欧版]
├[Passport_To_Barcellona][巴塞罗纳护照][ISO][欧版]
├[Passport_To_Paris][巴黎护照][ISO][欧版]
├[北欧女神]
├[爆笑筋肉人][日版]
├[波斯王子-武者之心][PrinceofPersia-Revelations][美版]
├[波波罗克洛伊斯物语][PopolocroisStoryAdventureofPrincePietro]
├[暴力橄榄球][Blitz_Overtime][美版]
├[BLOOD+最后的和平]
├[波斯王子竞争之剑][欧版]
├[布鲁克小镇-成熟季节][美版]
├[变形金刚游戏版][美版]C:
├[超级泡泡龙][UltraPuzzleBobblePocket][美版]
├[丛林大反攻][ISO][欧版]
├[卡普空-街机游戏合集-重装上阵][美版]
├[超级机器人大战MX携带版][日版]
├[宠物大冒险2][NeopetsPetpetAdventuresTheWandOfWishing][美版]
├[吃豆人世界拉力][Pac-Man_World_Rally][美版]
├[吃豆人世界3][Pac-ManWorld3][美版]
├[冲破火网黑鹰][欧版]
├[冲浪企鹅][美版]D:
├[地牢围攻-痛苦王座][ISO][美版]
├[戴夫·米拉自行车越野挑战赛][ISO][美版]
├[动感小子][日版]
├[德贝赛马2006]
├[大战略2]
├[DTM极速房车赛3][欧版]
├[弹珠台名人堂][Pinball-HallofFame][美版]
├[DQ与FF富豪街]
├[[DJMAX2][韩版]
├[[大家的地图2][日版]E:
├[恶代官漫游记][ISO][日版]
├[恶灵骑士][美版]
├[EA经典游戏合集][美版]
├[疯狂小旅鼠][Lemmings][美版]
├[福特街头赛车][ISO][美版]
├[FootballManager2007足球冠军经理]
├[福福之岛]
├[飞行大考验-名机总动员][日版]
├[疯狂橄榄球07][MaddenNFL07][美版]
├[反重力赛车]
├[分裂细胞][SplinterCellEssentials][美版]
├[Fifa足球07]
├[F1方程式赛车2006携带版][ISO][日版]G:
├[感染][ISO][欧版]
├[国际足球大联盟07][ISO][欧版]
├[怪物猎人][日版]
├[咕噜小天使][日版]
├[公主皇冠]
├[古惑狼赛车]
├[高达战争混战]
├[SD高达G世纪携带版高速下载]
├[怪物猎人携带版2nd][日版]
├[怪物猎人携带版2nd][汉化版]H:
├[火暴狂飙-传奇][BurnoutLegends][美版]
├[火影忍者究级携带版无幻城之卷]
├[幻想传说全程语音版日版]
├[横冲直撞传奇]
├[合金装备电子漫画]
├[合金装备掌上行动][Metal_Gear_Solid_Portable_Ops][美版]
├[皇牌空战X诡影苍穹][ISO][中文]
├[荒野神枪摊牌][Gun_Showdown][美版]
├[红侠乔伊][Viewtiful_Joe_Red_Hot_Rumble][美版]
├[海绵先生黄色复仇者][SpongeBob_Squarepants_The_Yellow_Avenger][美版]
├[海豹突击队-Bravo火线小组][SOCOM-U.S.NavySEALsFireteamBravo][美版]
├[虹吸战士]
├[[合金弹头]
├[[火热大脑美版]J:
├[街头篮球][NBABallersRebound][美版]
├[教父-暴徒战争][The_Godfather_Mob_Wars][美版]
├[降世神通-最后的空气大师][ISO][美版]
├[剑舞者千年之约定][Blade_Dancer][中文版]
├[吉他小子现场版][UMDRIP][欧版]
├[街舞男孩][ISO][欧版]
├[机动战士高达大混战][ISO][日版]
├[街头霸王Alpha3][Street_Fighter_Alpha_3_Max][美版]
├[家庭星空-携带版][ISO][日版]
├[极限滑雪][SSX-OnTour][美版]
├[极品醉车-消除器][Juiced-Eliminator][美版]
├[极品飞车-最高通缉][NeedforSpeed-MostWanted][美版]
├[极品飞车10卡本峡谷之城市争霸][ISO][欧版]
├[金字塔祖玛][Luxor_The_Wrath_Of_Set][美版]
├[极魔界村]
├[激·战国无双]
├[究极大越野][MX_Vs_ATV_Unleashed_On_The_Edge][美版]
├[金刚][KingKong][美版]
├[NFL街头橄榄球][NFLStreet2Unleashed][美版]
├[家庭伙伴][Family_Guy][美版]
├[加勒比海盗-亡灵财富][PiratesoftheCaribbean-DeadMan'sChest][美版]
├[极限滑雪][SSX-OnTour][美版]
├[极乐岛][ISO][欧版]
├[[机密武装]
├[[机动战士SEED联合VS扎夫特]
├[[极道无限76]
├[[加勒比海盗3世界尽头]
├[[劲舞团]K:
├[坎贝拉的非洲狩猎][ISO][美版]
├[狂乱:底特律街区][欧版]
├[口袋赛车][ISO][美版]
├[狂野口袋撞球][ISO][美版]L:
├[洛克人X反乱猎人][MegaManMaverickHunterX]
├[伦敦黑帮][Gangs_Of_London][美版]
├[乐克乐克][美版]
├[洛城飚车]
├[龙珠Z-真武道会][DragonBallZ-ShinBudokai][美版]
├[龙骑士][Eragon][美版]
├[篱笆墙外疯狂的哈米][Over_The_Hedge_Hammy_Goes_Nuts][美版]
├[乐高星球大战2原创三部曲][LEGO.Star.Wars.II.The.Original.Trilogy][美版]
├[老虎伍兹]
├[[廉价2500系列携带版VOL.9THE我的出租车][日版]
├├[007来自俄罗斯的爱][美版]
├[洛奇][美版]
├[沥青都市赛车][欧版]
├[龙珠Z真武道会][欧版]├[龙的传人][美版]M:
├[魔法气泡狂热版]
├[模拟人生2][Sims2,The][美版]
├[模拟人生2宠物][ISO][美版]
├[美国棒球联盟][MLB][美版]
├[迈阿密风云][MiamiVice-TheGame][美版]
├[摩托GP][ISO][美版]
├[美国职业篮球联赛'07][ISO][美版]
├[美少女梦工场4携带版][ISO][日版]
├[美国职业摔角联盟2007][WWE_Smackdown_Vs_Raw_07][美版]
├[美国大学-橄榄球07][ISO][日版]
├[魔界战记携带版]
├[摩托GP]
├[PSP麻将格斗俱乐部全国对战版]
├[模拟乐园惊奇世界][Thrillville][美版]
├[Marvel:终极联盟]
├[MTX越野摩托][美版]
├[马赫空战英雄][美版]
├[美国职业棒球大联盟07][美版]
├[美国职业棒球大联盟2K7][美版]
├[漫画同人会-携带版][ISO][日版]
├[漫画英雄集换式卡片游戏][美版]
├[[魔法数独MagicSudoku][欧版]
├[[模拟人生2][中文版]N:
├[能量宝石收藏版][Power_Stone_Collection][美版]
├[娜娜日版]
├[女神的笑壶][ISO][日版]
├[NHL冰球07][NHL07][美版]
├[Namco博物馆2][日版]
├劲爆美国职业篮球联赛(NBA2007)O:
├[奥特曼战斗进化]
├[欧洲锦标赛][日版]P:
├[扑克&赌场][PayoutPoker&Casino][美版]
├[啪啦啪啦啪][ISO][日版]
├[Puyo15周年纪念版][日版]Q:
├[拳击之夜3][Fight_Night_Round_3][美版]
├[汽车总动员][Cars][美版]
├[拳手之路2真实][ISO][日版]R:
├[荣誉勋章英雄][Medal_of_Honor_Heroes][美版]
├[忍者神龟][美版]
├[忍者神龟][欧版]
├[索尼克竞争者][Sonic_Rivals][美版]
├[速度与激情消除器][美版]
├[水银][ArcherMaclean'sMerbcury][美版]
├[水银融化][ISO][欧版]
├[狩猎季节][Open_Season][美版]
├[世界扑克巡回大赛][WorldPokerTour][美版]
├[世嘉MD经典合集收藏版][Sega.Mega.Drive.Collection][欧版]
├[史莱克冲撞][Shrek_Smash_N_Crash][美版]
├[杀戮地带解放][Killzone_Liberation][美版]
├[赏金猎犬中文版][BountyHounds][中文版]
├[三国志6][SanGokuShiVI][中文版]
├[索尼狗][TheDogHappyLife]
├[PSP死神][Bleach-HeattheSoul][日版]
├[死神-魂之热斗2][Bleach-HeattheSoul2][日版]
├[死神灵魂升温3][Bleach_Heat_The_Soul_3][日版]
├[数独SUDOKU][日版]
├[实况足球10][日版]
├[山脊赛车2][ISO][欧版]
├[杀戮地带-解放][ISO][美版]
├[实况棒球]
├[圣女贞德]
├[神秘岛][美版][最新dump版]
├[史酷比狗狗-谁在看谁][ISO][美版]
├[圣魔战记对混沌世代][ISO][日版]
├[沙滩机车赛专业版][ISO][美版]
├[疤面煞星]
├[少林决胜][ISO][美版]
├[谁想成为百万富翁-派对版][ISO][欧版]
├[Simple2500系列网球]
├[世界传说-光明神话][ISO][日版]
├[世界斯诺克锦标赛2007][ISO][欧版]
├[失落神殿-魔窟的皇帝][ISO][日版]
├[实况足球2007][英文版]
├[斯巴达三百勇士光辉进军][美版]
├[使命召唤胜利之路][美版]
├[三国志八][日版]
├[世界七大奇迹][美版]
├[死神~炙热之魂4][美版]T:
├[天地之门][TenchinoMon][中文]
├[天地之门2武双传][ISO][中文]
├[托尼霍克的地下滑板2][TonyHawk'sUnderground2-Remix][美版]
├[铁拳-黑暗复苏][Tekken-DarkResurrection][美版]
├[脱逃大师][Exit][美版]
├[泰戈伍兹高尔夫巡回赛07][TigerWoodsPGATour07][美版]
├[头文字D公路传说][Initital_D_Street_Stage][日版]
├[天外魔境-第4默示录][TengaiMakyou-DaishinoMokushiroku][日版]
├[天秤彩球2携带版][Plus_Plum_2_Again_Portable][日版]
├[泰托怀旧记忆-口袋版][Taito_Memories_Pocket][日版]
├[太鼓达人便携版2][TaikonoTatsujinPortable2][日版]
├[泰托传奇-加强版][ISO][欧版]
├[泰格·伍兹高尔夫球巡回赛07][ISO][美版]
├[实战柏青嫂必胜法北斗之拳]
├[Talkman][最新dump版]
├[天堂的意志][ISO][日版]
├[THE随身美少女麻将][ISO][日版]V:
├[[VR网球][欧版]
├[[VR网球3][欧版]
├[V8超级房车赛3][欧版]W:
├[微型机器4][MicroMachinesV4][美版]
├[无尽传说勇者密码][UntoldLegends-TheWarriorsCode][美版]
├[舞HIME鲜烈-真-风华学园激斗史!][Mai-HimeSenretsu!][日版]
├[巫术帝国3霸王的系谱][Wizardry_III_Haou_no_Keifu][日版]
├[我的暑假-便携版][BokunoNatsuyasumiPortable][日版]
├[我们的块魂][ISO][日版]
├[我自己的迷宫][ISO][日版]
├[WWE摔角2006]
├[无限试驾]X:
├[星球大战-前线2][StarWars-BattlefrontII][美版]
├[星际战士][StarSoldier][美版]
├[星际迷航战术攻击][Star_Trek_Tactical_Assault][美版]
├[新天魔界-混沌世代IV][Generation_of_ChaosIV][美版]
├[小死神2邪恶的根源][Death_Jr_II_Root_Of_Evil][美版]
├[线条方块][Gunpey][美版]
├[心跳回忆永远属于你][Tokimeki_Memorial][日版]
├[寻找爱原史奈]
├[寻找爱星野亚希]
├[新纪幻想圣魔之魂2无限阵营][ISO][美版]
├[侠盗猎车-罪恶都市传奇][ISO][欧版]
├[小旅鼠大冒险]
├[席德梅尔的海盗][ISO][美版]
├[新彩虹岛-手风琴大冒险][日版]
├[线条方块][欧版]Y:
├[伊苏VI纳比斯汀的方舟][Ys_6_The_Ark_of_Napishtim][日版]
├[伊苏VI那比斯汀的方舟][ISO][美版]
├[云斯顿模拟竞速]
├[越野摩托车]
├[宇宙巡航机-合集][Gradius_Collection][美版]
├[游戏王对战怪兽GX卡片力量][Yu-Gi-Oh_GX_Tag_Force][美版]
├[英雄传说白发魔女]
├[音乐方块2][ISO][美版]
├[音乐爆破][Every_Extend_Extra][美版]
├[遗迹大冒险]
├[约束之地利维艾拉][Riviera][日版]
├游戏下载[亚斯特尼西雅物语][Astonishia_Story][美版]
├[勇敢的故事][BraveStory-AratanaruTabibito]日版]
├[英雄传说空之轨迹FC][Eiyuu_Densetsu_Sora_no_Kiseki_FC][日版]
├[英灵殿骑士][日版]
├[鱼之眼-携带版][ISO][日版]
├[鸭嘴兽][ISO][美版]
├[亚瑟与迷你王国][含五国语言][ISO][欧版]
├[野球拳]
├[益智解谜战神的挑战][美版]Z:
├[智力问答]
├[指环王战略版]
├[纸牌巡回赛]
├[职业钓鱼][RapalaTrophies][美版]
├[职业棒球联盟]
├[真·三国无双二度进化][Dynasty_Warriors_Vol_2][美版]
├[炸弹人]
├[战国无双]
├[战地指挥官][FieldCommander][欧版]
├[战锤阿特路玛之战][Warhammer_Battle_For_Atluma][美版]
├[罪恶装备审判][Guilty_Gear_Judgment][日版]
├[捉猴啦哔波猴赛车][Sarugetchu_Piposaru_Racer][日版]
├[真名法典][MagnaCartaPortable][日版]
├[炸弹人携带版][Bomberman_Portable][日版]
├[蜘蛛侠2][Spiderman_2][ISO][日版]
├[真人快打释放][Mortal_Kombat_Unchained][美版]
├[职业高尔夫-世界巡回赛2007][ISO][欧版]
├[战争地带][ISO][美版]
├[职业进化足球6][ISO][欧版]
├[在线象棋国度][ISO][美版]
├[战火兄弟连登陆日][美版]
├[最终舰队FinalArmada][欧版]
├[炸弹人大陆携带版][日版]
├[自由奔跑][欧版]
├[最终幻想周年纪念版][日版]
├[压碎][欧版]
├[最终幻想2周年纪念版][日版]
├[噪点][欧版]我给了这么多东西,把分给我吧!~
我发给你,不免费
其他1条回答
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。Force Escape ios V1.6iOS系统3DTouch全解析
招聘信息:
概述iOS10系统登录中国,在系统中对3D Touch的使用需求更频繁,所以对iOS9中便引入的3D Touch功能做一些了解是很有必要的在日常开发中,我们经常需要使用3D Touch中的两个功能在主屏幕上对应用图标使用3DTouch操作在应用程序内对某一控件使用3DTouch操作ShortcutItem概述ShortcutItem功能允许用户在主屏幕上对应用图标使用3DTouch操作,如果本次操作有效,则会给出几个快捷可选项允许用户进行操作静态添加在info.plist中添加UIApplicationShortcutItems关键字,以如下方式配置即可其中各个关键字释义如下:UIApplicationShortcutItemType: 快捷可选项的特定字符串(必填)UIApplicationShortcutItemTitle: 快捷可选项的标题(必填)UIApplicationShortcutItemSubtitle: 快捷可选项的子标题(可选)UIApplicationShortcutItemIconType: 快捷可选项的图标(可选)UIApplicationShortcutItemIconFile: 快捷可选项的自定义图标(可选)UIApplicationShortcutItemUserInfo: 快捷可选项的附加信息(可选)动态添加UIApplicationShortcutItem每一个快捷可选项是一个UIApplicationShortcutItem对象,其指定初始化器(NS_DESIGNATED_INITIALIZER)如下-&(instancetype)initWithType:(NSString&*)type&localizedTitle:(NSString&*)localizedTitle&localizedSubtitle:(nullable&NSString&*)localizedSubtitle&icon:(nullable&UIApplicationShortcutIcon&*)icon&userInfo:(nullable&NSDictionary&*)userI其中各个参数释义如下:type: 快捷可选项的特定字符串(必填)localizedTitle: 快捷可选项的标题(必填)localizedSubtitle: 快捷可选项的子标题(可选)icon: 快捷可选项的图标(可选)userInfo: 快捷可选项的附加信息(可选)UIApplicationShortcutIcon每一个快捷可选项图标为一个UIApplicationShortcutIcon对象,我们可以使用系统提供的多个图标,也可以自定义我们自己的图标//&使用系统提供的图标
+&(instancetype)iconWithType:(UIApplicationShortcutIconType)
//&自定义图标
+&(instancetype)iconWithTemplateImageName:(NSString&*)templateImageN系统提供的图标样式如下:注: 自定义图标需要使用镂空图标,同时建议1倍图标大小为35*35示例//&以"动态添加四个快捷可选项"为例
UIApplicationShortcutIcon&*searchShortcutIcon&=&[UIApplicationShortcutIcon&iconWithType:UIApplicationShortcutIconTypeSearch];
UIApplicationShortcutItem&*searchShortcutItem&=&[[UIApplicationShortcutItem&alloc]&initWithType:@"com.liupeng.search"&localizedTitle:@"Search"&localizedSubtitle:@"Search&Subtitle"&icon:searchShortcutIcon&userInfo:nil];
UIApplicationShortcutIcon&*playShortcutIcon&=&[UIApplicationShortcutIcon&iconWithType:UIApplicationShortcutIconTypePlay];
UIApplicationShortcutItem&*playShortcutItem&=&[[UIApplicationShortcutItem&alloc]&initWithType:@"com.liupeng.play"&localizedTitle:@"Play"&localizedSubtitle:@"Play&Subtitle"&icon:playShortcutIcon&userInfo:nil];
UIApplicationShortcutIcon&*qrShortcutIcon&=&[UIApplicationShortcutIcon&iconWithTemplateImageName:@"shortcut_QR"];
UIApplicationShortcutItem&*qrShortcutItem&=&[[UIApplicationShortcutItem&alloc]&initWithType:@"com.liupeng.qr"&localizedTitle:@"QR"&localizedSubtitle:@"QR&Subtitle"&icon:qrShortcutIcon&userInfo:nil];
UIApplicationShortcutIcon&*payShortcutIcon&=&[UIApplicationShortcutIcon&iconWithTemplateImageName:@"shortcut_pay"];
UIApplicationShortcutItem&*payShortcutItem&=&[[UIApplicationShortcutItem&alloc]&initWithType:@"com.liupeng.pay"&localizedTitle:@"Pay"&localizedSubtitle:@"Pay&Subtitle"&icon:payShortcutIcon&userInfo:nil];
[UIApplication&sharedApplication].shortcutItems&=&@[searchShortcutItem,&playShortcutItem,&qrShortcutItem,&payShortcutItem];触发回调当用户通过点击快捷可选项进入应用程序会回调如下方法,我们可以在这里通过快捷可选项的type来加以区分,以便进行不同的操作-&(void)application:(UIApplication&*)application&performActionForShortcutItem:(UIApplicationShortcutItem&*)shortcutItem&completionHandler:(void&(^)(BOOL))completionHandler
&&&if&([shortcutItem.type&isEqualToString:@"com.liupeng.search"])
&&&&&&&//&do&something&...
&&&else&if&([shortcutItem.type&isEqualToString:@"com.liupeng.play"])
&&&&&&&//&do&something&...
}注意在动态添加快捷可选项前,需要用判断是否支持3D Touch功能,以免在不支持的设备上运行程序导致闪退if&([self&respondsToSelector:@selector(traitCollection)])
&&&if&([self.traitCollection&respondsToSelector:@selector(forceTouchCapability)])
&&&&&&&if&(self.traitCollection.forceTouchCapability&==&UIForceTouchCapabilityAvailable)
&&&&&&&&&&&//&支持3D&Touch
&&&&&&&else
&&&&&&&&&&&//&不支持3D&Touch
}注: 在支持3D Touch的设备上,用户可以在程序运行期间通过设置 -> 通用 -> 辅助功能 -> 3D Touch来关闭3D Touch功能,所以我们有必要通过重写-traitCollectionDidChange:方法随时处理Peek & Pop概述Peek和Pop是应用内的一种全新交互模式,当用户不断增加力量在控件上按压,会依次进入四个阶段轻按控件,除触发Peek的控件外,其他区域全部虚化继续用力Peek被触发,展示Pop界面快照向上滑动展示快捷选项继续用力跳转进入Pop界面使用以"从ViewController中的UILabel控件通过Peek & Pop进入DetailViewController"为例,对Peek & Pop的使用进行一下讲解需要实现Peek & Pop交互的控件所在的控制器遵守UIViewControllerPreviewingDelegate协议@interface&ViewController&()&
@end在控制器内为需要实现Peek & Pop交互的控件注册Peek & Pop功能[self&registerForPreviewingWithDelegate:self&sourceView:label];当进入Peek状态时,系统会回调如下方法-&(nullable&UIViewController&*)previewingContext:(id&)previewingContext&viewControllerForLocation:(CGPoint)location
&&&//&previewingContext.sourceView:&触发Peek&&&Pop操作的视图
&&&//&previewingContext.sourceRect:&设置触发操作的视图的不被虚化的区域
&&&DetailViewController&*detailVC&=&[[DetailViewController&alloc]&init];
&&&//&预览区域大小(可不设置)
&&&detailVC.preferredContentSize&=&CGSizeMake(0,&300);
&&&return&detailVC;
}当进入Pop状态时,系统会回调如下方法-&(void)previewingContext:(id&)previewingContext&commitViewController:(UIViewController&*)viewControllerToCommit
&&&[self.navigationController&pushViewController:viewControllerToCommit&animated:YES];
}在Peek时希望提供一些快捷选项,需要在DetailViewController中重写previewActionItems的getter方法-&(NSArray<id>&*)previewActionItems
&&&UIPreviewAction&*action1&=&[UIPreviewAction&actionWithTitle:@"选项一"&style:UIPreviewActionStyleDefault&handler:^(UIPreviewAction&*&_Nonnull&action,&UIViewController&*&_Nonnull&previewViewController)&{
&&&UIPreviewAction&*action2&=&[UIPreviewAction&actionWithTitle:@"选项二"&style:UIPreviewActionStyleSelected&handler:^(UIPreviewAction&*&_Nonnull&action,&UIViewController&*&_Nonnull&previewViewController)&{
&&&UIPreviewAction&*action3&=&[UIPreviewAction&actionWithTitle:@"选项三"&style:UIPreviewActionStyleDestructive&handler:^(UIPreviewAction&*&_Nonnull&action,&UIViewController&*&_Nonnull&previewViewController)&{
&&&UIPreviewActionGroup&*actionGroup&=&[UIPreviewActionGroup&actionGroupWithTitle:@"选项组"&style:UIPreviewActionStyleDefault&actions:@[action1,&action2]];
&&&return&@[action1,&action2,&action3,&actionGroup];
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量6265点击量4590点击量4565点击量3500点击量2909点击量2409点击量2381点击量2351点击量2333
&2016 Chukong Technologies,Inc.
京公网安备89小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
Migrating your code to Objective-C ARC
Recently, Apple introduced several new developer stuff including Xcode 4, ARC, LLVM Compiler 3.0 and iOS 5. From some of the questions on Stack overflow, I could understand that, most of the ARC related confusions arise due to the fact that, developers don&t know if &ABC& is a feature/restriction of LLVM 3.0 or iOS 5 or ARC.Retain cycles, auto-release pools, @autorelease blocks, oh man! So many new things? What am I going to do? You are right. ARC, or Objective-C Automatic Reference Counting is almost&. No really.In this post, I&ve made an attempt to demystify the air around this. Before starting, I&ll have to warn you that, this is a fairly long post. If you are too bored, Instapaper this article and read it later. But, hopefully, at the end of this, I believe, you will have a better understanding on how ARC works and be able to work around the innumerable errors it spits out when you convert your project.Having said that, let&s get started.Contents
What is ARC
Problems with the current model.
Garbage collection
Reference Counting
Automatic Reference Counting
Compiler level feature
Also a run time feature
ARC Ownership qualifiers
ARC knows more Objective-C than you
Toll-free bridging
How does ARC work internally?
ARC front end
ARC optimizer
The actual Migration using Xcode 4.2
Common ARC migration errors
Cast of Objective-C pointer to C Pointer type
performSelector may cause a leak because its selector is unknown
Receiver type "*" doesn't declare the method with selector "*"
Common workarounds that you use in ARC on code that otherwise looks normal
Capturing "*" strongly is likely to lead to a retain cycle
Avoiding early releases using __block
That last question
When should you migrate?
Where to go from here?&What is ARCARC is a feature of the new LLVM 3.0 compiler that helps you to write code without worryingmuch&about memory management. Memory management can be broadly classified into two, garbage collected and reference counted models. Before going to the details, let&s briefly discuss these two models and understand why ARC is even needed.Problems with the current model.The current memory model we use in Objective-C is manual reference counting on iOS and Garbage collection on Mac.There are certain problems with both these memory models which probably was the reason why ARC was developed.Garbage collectionGarbage collection is a higher level language feature probably introduced in Java (or technically, Java Virtual Machine) and implemented in a variety of other programming platforms including Microsoft&s Common Language Runtime. While Garbage collection worked well for higher level languages, Objective-C, which is still C under the hood, didn&t really fly high. Pointers (or rather references) in other languages like Java were actually objects that managed retain count and automatically releases itself when the count reaches zero. One of the design goals of C was to be optimized for performance and not &easy of use&. While pointer objects (read&) are great object oriented abstractions, they have an adverse effect on the performance of the code and since Objective-C was intended primarily for native programming where developers are used to use pointers, pointers within a structure, pointer to a pointer (for dereferencing a out parameter), it was just too difficult to introduce something like a smart pointer that would require a lot of mindset change from the developers who prefer a deterministic memory management model (Reference counting) over a non-deterministic memory management model (Garbage collection). Nevertheless, GC (Generational GC) was introduced in Objective-C 2.0 for Mac. While Generational GC doesn&t suffer from &Stop the world& issues like the mark and sweep alogrithm, they don&t collect every released variable and an occasional mark and sweep collection is still needed.Reference CountingThe memory management model used in iOS is called as reference counting model, or more precisely, manual reference counting.In manual reference counting model, you as a developer, have to deallocate every object you allocated. When you don&t do this, you either leak memory or over release it, causing a crash. While that counting sounds easy, Most of the memory leaks happen when you transfer ownership of objects across scope boundaries. That&s a creator method that allocates an object for you and expects the caller to deallocate it. To circumvent this problem, Objective-C introduced a concept called autorelease. auto-released variables are added to the auto-release pool and are released at the end of the runloop. While this sounds too good, auto-release pools do incur an additional overhead.For example, comparing the two code blocks,
NSDictionary *dict = [[NSDictionary alloc] init];
// do something with the dictionary here
// I'm done with the dictionary, I don't need it anymore
[dict release];
// more code}
NSDictionary *dict = [NSDictionary dictionary]; // auto-released object
// do something with the dictionary here
// I'm done with the dictionary, I don't need it anymore&
// more code}
the first block is an example of optimized use of memory where as the second depends on auto-release pools. While this block of code doesn&t really incur significant memory overhead, code like these slowly adds together and makes your reference counted model heavily dependent on auto-release pools. That is, objects that you know could be deallocated, will still linger around in the auto-release pool for a little longer.Automatic Reference CountingSay hello to ARC. ARC is a compiler feature that auto inserts retain and release for you. So in the first code block of the above example, you no longer have to write the release method and ARC auto-inserts for you before compilation.
NSDictionary *dict = [[NSDictionary alloc] init];
// do something with the dictionary here
// I'm done with the dictionary, I don't need it anymore
[dict release]; // ARC inserts this code for you.
// more code}
When you create an autoreleased object, like in the second block of code, ARC compiler is clever enough not to add a release call. Sound great, so how should I go about doing this ARC thing? Just delete all release/retain codes and pray? Unfortunately, it isn&t that easy. ARC is not just some auto insert or macro expander kind of tool.&It forces you to think in terms of object graphs instead of memory allocation, retain or release.&Let&s delve a little deeper into ARC.Compiler level featureARC is a compiler level feature. I repeat. ARC IS A COMPILER LEVEL FEATURE. This means, when you use ARC, you don&t have to worry about upgrading your deployment target and so on. However, only the latest LLVM 3.0 compiler supports ARC. If you are still stuck with GCC, you are out of luck. (Meh!) Some more points that you should know about ARC are,
ARC is backward compatible with libraries and framework compiled with under non-ARC.
ARC can be used within your project on a file-by-file basis. So you can mix and match ARC code with non-ARC code.
You can also integrate ARC compiled libraries into your project that doesn&t use ARC and vice-versa.
You use a&compiler switch&to turn ARC on and off.
(The keyword here is compiler switch)
You can also set the complete target to build with ARC by default (and use non-ARC compiler only when instructed so.) This is shown in the illustration below.
The two main compiler switches that you would often use are when you build your application with a third party library that is not ARC compliant and vice versa, are
-fno-objc-arc
-fobjc-arc
-f is the switch and&no-objc-arc&and&objc-arc&are the options that you are turning on. As evident from the names, the first one turns off ARC and the second turns on.For example, if your application is ARC enabled but a third party library is not, you use the first switch&-fno-objc-arcto exclude the third party library. Conversely, if your application is not yet ARC enabled (gasp!) but the third party library you are integrating is, you use the second switch&-fobjc-arc&You add these flags to the project from the Build phases tab as shown below.Also a run time featureWait! You just told me (and repeated) that ARC is a compiler level feature? Now what? Sorry, I hear you, but, unfortunately, things aren&t that easy and it doesn&t just stop here. ARC also backs up on a runtime feature calledzero-ing weak references. Oh, damn, another keyword! I should have introduced this before. But that&s ok. We will revisit about the run-time dependency of ARC, a little later in this post.ARC Ownership qualifiersAs I showed you earlier, ARC automatically inserts releases and retains in your code in a pre-compilation step. But for ARC to know when to release your objects and when to retain them, you need to somehow tell the life of your variables. You use ownership qualifiers for that. A strong understanding of ownerships is vital to understand and use ARC properly. Once you understand this concept, you will be thinking in terms of object graphs instead of retain/release. Secondly, when you use ARC, all variables local or ivars are initialized to nil automatically for you. This means, there is little chance of having a dangling reference in your application.
__unsafe_unretained
__autoreleasingThe first qualifier, __strong, is the default and you might not even be using this explicitly. It is use to tell the ARC compiler that, the declared variable &owns& the reference. The opposite of this is __weak, which tells the ARC compiler that the declared variable doesn&t own the reference.The __weak is&synonymous&to the &assign& modifier. You normally use assign modifier for IBOutlets and delegates. Under ARC, this is replaced with __weak. However, there is a caveat. __weak requires you to deploy the app on a runtime that supports&zero-ing weak references. This includes, iOS 5 and Lion. Snow Leopard and older operating systems or iOS 4 and older operating systems don&t support zero-ing weak references. This obviously means you cannot use __weak ownership modifiers if you plan to deploy to older operating systems. Fret not. ARC includes another ownership qualifier, __unsafe_unretained that is synonymous to __weak, except that when the pointer is de-referenced, it is not set to nil, but remains dangling. A while ago, I told something about zero-ing weak references? When the runtime supports zero-ing weak references, your __weak variables are automatically set to nil when they are released. This is the only feature that requires a higher deployment target (iOS 5/Lion). Otherwise, you are good to deploy on iOS 4/Snow Leopard.A couple other important things to know about __weak vs __unsafe_unretained is that, the compiler doesn&t allow you to use __weak when your deployment target is set to a operating system that doesn&t support zero-ing weak references. The Convert to Objective-C ARC wizard uses __weak only when your deployment target supports zero-ing weak references. So if your deployment target is iOS 4, the Objective-C convert ion wizard will replace assign modifiers with __unsafe_unretained instead of __weak.The last ownership qualifier, __auto_releasing is used mostly when passing a reference to a function for writing out. You would use this in places where you normally use pointer indirection like returning a NSError object via an out parameter.Properties in your header file can also have the above ownership qualifiers except the __auto_releasing. When applied to properties, ARC automatically generates the correct code in dealloc to release them when the object dies.Lastly, and more importantly, all of ARC managed&objects&are initialized to nil when they are created. So, again, no more dangling pointers because you forgot a initialize statement. However, do note that this initialization doesn&t initialize primitive data types. So a declaration like,
might contain a garbage value for a.Whew! That&s pretty taxing. Take a break. We just started.ARC knows more Objective-C than youARC also taps into a the Objective-C language naming conventions and infers the ownership of the returned object.In Objective-C, a method that stats with any one of the following prefix,
mutableCopy and
neware considered to be transferring ownership of the returned object to the caller.This means, in your application, when you create a method, ARC automatically infers whether to return a autoreleased object or a +1 retained object from your method name. In fact, in most cases, instead of returning auto-release objects, ARC just inserts a manual release in the calling code, automatically for you. However, there is a small caveat. Let&s assume that you have a method that starts with &copy&, as in
-(NSString*) copyRightS
ARC assumes that it would transfer the ownership of the returned string to the caller and inserts a release automatically. Everything works well, if both the called method and the calling method are compiled using ARC.
But&if your &copyRightString& method is in a third party library that isn&t compiled with ARC, you will over-release the returned string. This is because, on the calling code, ARC compiler inserts a release to balance out the retain count bumped up by the &copy& method. Conversely, if the third party library is compiled with ARC and your method isn&t, you will have a memory leak. You can however override this behavior by adding one of the following attribute to your methods.
NS_RETURNS_NON_RETAINED
NS_RETURNS_RETAINEDSo your method will now look like this.
-(NSString*) copyRightString NS_RETURNS_NON_RETAINED;
You can also rename the method name to&copyrightString&(note the case) or&getCopyRightString&instead of adding an attribute. However, I wouldn&t recommend the former method as it breaks the cocoa naming conventions (prefixing a method with &get& or &set& is Java-ish)You will see methods having the NS_RETURNS_* prefixes throughout the header files in Apple&s own UIKit.framework or the foundation classes. Now that you know what happens behind the scenes and how compiler treats these decorations, you can solve crazy memory issues, like a crash when you call a&copyRightString&in your method in a third party library.With that, let&s get ready for climbing the next peak.Toll-free bridgingARC&doesn&t&manage Core Foundation objects. They say, there is no free lunch. ARC, takes it one step further. There is no free-casting between Core Foundation objects and equivalent Objective-C objects (NS* objects). Yes, that&s right. You cannot cast a Core Foundation object to an equivalent Objective-C object (NS* object) without telling ARC how to manage ownerships.Let&s now see how to specify ownership transfers when you cast a Core Foundation object.The following ownership transfer modifiers should be provided when you cast a Objective-C object to a Core Foundation object.
__bridge_retained
__bridge_transferWhen you migrate a project to ARC, you would have seen error messages like the one below.
ARC Error because of a missing bridge attribute in a Toll-free bridging codeYou might also have proceeded by accepting the suggestions provided by the LLVM compiler. But now, let&s dig deeper and understand the &why& behind it.The modifier, __bridge tells the ARC compiler that, it&s a plain simple, bridging cast. That means, you ask the ARC compiler to do nothing extra when the transfer is made. You might think, if that is the case, Apple could have made this the default choice. But it was not made probably because, it&s to preposterous to make such an assumption. Making such a bold assumption means, you would easily leak memory as there isn&t a easier way to tell when you are actually releasing a Core Foundation object unlike a Objective-C object.The second modifier, __bridge_retained is used to tell the ARC compiler that the Objective-C object should be transferred to Core Foundation by bumping the retain count by 1 and it should be treated as if it is a newly created object (as opposed to a auto-released object). You use this modifier if the method was probably named like a creation method (starting with init, copy, mutableCopy etc.,) or if you are going to release the Objective-C object inside of Core Foundation using methods like CFRelease.The last modifier, __bridge_transfer is used to tell the ARC compiler that the Core Foundation object is to be transferred to ARC with a retain count of 1. This is used if you created a Core Foundation object using one of the CF***Create methods and want the ARC compiler to handle the memory management for you. That&s you are transferring a Core Foundation object to ARC with a retain count of 1.As a side note on this, avoid using __bridge_retained and __bridge_transfer to trick the compiler to add retain and releases for you. Use it to improve your code readability and minimizing the number of manual memory management calls. (Move on if you don&t understand this line. You will start understanding this automatically when you start using this in your own code)How does ARC work internally?ARC ain&t magic, if you know how it works. But a little knowledge is a dangerous thing. Knowing how the ARC compiler works will help you more in understanding the error messages and compiler warnings spat out by it.The ARC compiler has two main parts, a front end compiler and an optimizer.ARC front endThe ARC front end compiler checks for every &owned& Objective-C object and inserts release appropriately. By owned object, I mean, an object whose ownership qualifier has been set. For example, if the &owned& object is a local variable, ARC front end compiler inserts a release at the end of the scope. This is because, by default all local variables are &strong& ly owned. If the object is a instance variable, the ARC front end compiler inserts a release statement in the dealloc method, if the ownership type is strong. For unsafe_unretained or weak ownership ARC doesn&t do anything. It also takes care of calling the [super dealloc] for you and intact ARC compiler doesn&t allow you to explicitly call dealloc.The ARC front end compiler also takes care of generating errors when it encounters a variable (local or instance) whose ownership qualifier is not set or when you explicitly calling dealloc.ARC optimizerThe function of the ARC optimizer is to optimize the retain and release statements by removing them if they are inserted multiple times by the ARC front end compiler. It is this optimizer that ensures that performance is not affected by calling retain and release multiple times.The actual Migration using Xcode 4.2Xcode 4.2 has a wizard to automatically migrate your code for use with the ARC compiler. This means, the wizard rewrites some of your code, removes calls to retain/release and removes dealloc methods and calls to [super dealloc] for you.The first step is to open your project, select Edit -& Refactor -& Convert to Objective-C ARC from the menu.
Migrating to Objective-C ARC using Xcode 4.2When you select this option, you will be asked to select a target. If you have only one target, it&s fine. If you have multiple targets in your application, you have to perform the ARC migration on every target. After you select a target, the wizard by default selects all source code files that belong to that project for ARC migration. If you are using third party libraries that are not yet ARC ready, you can uncheck those files in this step. This is illustrated in the screenshot below.
Selecting your files for ARC exclusionIn the above project, since I know that ASIHttpRequest is not yet ARC compatible, I&m selecting them and command-clicking them to show the option to uncheck all of them. When you do this, the wizard automatically adds a -fno-objc-arc compiler flag for all these files.The next step is to start the pre-checking process. The pre-checking process compiles the project and analyzes for potential problems before performing the actual migration. You might almost and always get a error message like this.
The dreaded error message!Of course, 58 errors in this screenshot is actually quite low. You should expect anywhere in the range of 300+ for a mid sized project. But fret not, they aren&t complicated at all to fix.Common ARC migration errorsThe number of errors that might prevent you from converting your project to ARC is usually high if your code is &old& or if it doesn&t adhere to Objective-C design patterns. For example, accessing a iVar. While it&s technically ok, you should almost and always use properties to access them outside of init and dealloc methods. If you have been using properties, ARC migration would be painless. If you were old skool, you have to feel the pain now. In this last section, I&ll show you the most commonly occurring errors when you migrate your project.Cast of Objective-C pointer to C Pointer typeThis error is generated because ARC doesn&t do toll-free bridging for you. As I explained before in the section, Toll-free bridging, requires the developer to explicitly specify ownership transfer qualifiers.Use the various ownership transfer qualifiers I showed you before to fix this problem.performSelector may cause a leak because its selector is unknownWe now know that Objective-C ARC compiler knows more Objective-C than you. This error message is because of that. The ARC compiler tries to identify the method family and determine whether to add a retain or release to the returned value from the caller code. This means, if your method starts with init, alloc, copy, mutableCopy or new, the ARC compiler will add a release to the calling code after the variable scope ends. Since are using a selector to call a method dynamically at runtime, ARC doesn&t really know if the method called returns a +1 retained object or a auto-released object. As such, ARC cannot reliably insert a retain or release to the returned object after its scope ends. This warning is shown to warn you of potential memory leaks.If you are sure that your code works fine without memory leaks, you can ignore this warning. To suppress this warning, you can turn off the compiler flag -Warc-performSelector-leaks warning on a line by line basis like this.
#pragma clang diagnostic push#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:self.mySel]; #pragma clang diagnostic pop
Unfortunately, you cannot annotate a dynamic selector using __attribute__ ((objc_method_family(*))).Receiver type &*& doesn&t declare the method with selector &*&ARC mandates that every method you call should be declared properly. With GCC, this was a warning. But LLVM makes this step mandatory since ARC needs to accurately identify and that is why you see an error like this.
Error that you see when you don't declare a receiver typeThis error is also because of the fact that ARC needs to identify the method family to determine if it has to add a retain or release to the returned object. For example, in the above code, the method, returnMyGreatObject might return a NS_RETURNS_RETAINED. In this case, the ARC compiler has to insert a release after the returned object goes out of scope. The ARC compiler can know this only when you declare it formally. This is why, under ARC method declarations are mandatory. If you have been declaring methods formally under GCC, even when the compiler didn&t enforce (so that the code was aesthetically beautiful) you wouldn&t see this error at all. As I said before, the number of ARC migration errors is directly proportional to the quality of code you write. Fixing this error is fairly simple and all you have to do is to declare every method formally in the header file or on a private category extension.Common workarounds that you use in ARC on code that otherwise looks normalIn some cases, while using ARC, you might end up writing code that looks as if it&s written to &please& the ARC compiler rather than writing natural code. Unfortunately, nothing can be done to this and we all have to live with this. The next two sections explain when you might need to write unnecessary code like this to please the compiler.Capturing &*& strongly is likely to lead to a retain cycle
ARC and retain cyclesThe last category of warning message is shown when a retain cycle is detected in your code. An example is shown below.This code was probably leaking the request object before ARC and increasing your memory footprint. But, thanks to ARC. You now know that code like these cause retain cycles that cannot be released automatically. Circumventing a retain cycle issue almost and always ends up breaking the cycle with a weak reference.Fixing this error is fairly simple and in this case, you can get a weak reference to the request object and copy it to the block. Within the block, convert it again to a strong reference. This is illustrated below.
Workaround for ARC and retain cycle issueIn the above code block, you can also replace references to __unsafe_unretained with __weak if you are deploying to a runtime that supports zero-ing weak references.Avoiding early releases using __blockSometimes, you need an object to live till as long as the completion handler on it can live. For example, a Block based UIAlertView can call a completion handler after the user presses a button on the UIAlertView.For example,
UIAlertView *alertView = [UIAlertView alertViewWithTitle:@"Test" buttons:[NSArray arrayWithObjects:@"Ok", @"Cancel", nil] completionHandler:^(int tappedButtonIndex)
{& // do something based on the button tapped on alertView}];[alertView show];
In the above case, the alertView gets deallocated by ARC as soon as it&s shown and the call to completionHandler never gets executed (or even crashes).To prevent this, you can use the __block decoration on UIAlertView declaration and copy it inside the block like
__block UIAlertView *alertView = [UIAlertView alertViewWithTitle:@"Test" buttons:[NSArray arrayWithObjects:@"Ok", @"Cancel", nil] completionHandler:^(int tappedButtonIndex)
{& // do something based on the button tapped on alertView alertView = nil;}];[alertView show];
ARC takes care of releasing it when you nil it inside the completionHandler. You will find this pattern used a lot when you work with completionHandlers in TwTweetComposeViewController or even UIViewController presentViewController:animated:completion: methods.Of course, you should de-reference the strong pointers using __weak or __unsafe_unretained (non-zeroing weak references runtime)That last questionWhen should you migrate?
NOWThe performance benefits you get by using ARC is remarkable. Apple claims that the @autoreleasepool is over 6 times faster than NSAutoReleasePool objects used in your non-ARC code. This is because, @autoreleasepools don&t allocate objects and all it does is must bump up the pointer retain counts. Similarly, NSObjects& retain and release are optimized that you can expect a performance boost of anywhere around 2.5x. The third important performance benefit you will see is in methods that return autoreleased object. Under ARC, this variable is no longer transferred using the auto-release pool and what instead happens is a ownership transfer. Again this is upto 20x faster.Hence, don&t wait till your dependent third party frameworks are migrated to ARC. You can always exclude them and go ahead and convert your code to ARC now.Where to go from here?
WWDC 2011 & Session 322 Introduction to Automatic Reference Counting
WWDC 2011 & Session 322 Objective-C Advancements in depth
Stop: You are warned. This link is only for hard code geeks.
WWDC 2011 & Session 308 & Blocks and Grand Central Dispatch in PracticeOne last word, treat this post as a living document. I&ll be updating the last few sections on new workarounds as and when I find a fix for them.&Mugunth
on Twitter
webApp添加到iOS桌面
iOS中的safri浏览器可以将一个网页添加到桌面,当做一个独立的应用运行。当然,这里我们不讨论怎么去做一个webApp,这需要html5的相关知识和开发经验。这里我们只讲webApp添加桌面后到启动的相关细节。全屏显示:&meta name="apple-mobile-web-app-capable" content="yes" /&系统顶栏的颜色(黑色和白色):&meta name="apple-mobile-app-status-bar-style" content="white" /&&meta name="apple-mobile-app-status-bar-style" content="black" /&桌面程图标(如果不设置,则图标会显示网页的截图):&link rel="apple-touch-icon" href="icon.png" /&但是,iOS会自作多情的给这个图标加上高光,如果想图标不被高光,可以这样:&link rel="apple-touch-icon-precomposed" href="icon.png" /&如果想给不同的设备匹配不同的icon,可以加上size属性:&link rel="apple-touch-icon" size="72x72" href="icon-ipad.png" /&&link rel="apple-touch-icon" size="114x114" href="icon-iphone4.png" /&程序启动的过程中,需要指定启动画面,否则,白屏或者截图是让人很不愉悦的。iOS有ipad和iPhone/ipod touch之分。ipad的启动画面是横竖屏分开的,画面的尺寸必须是8*1024。iPhone和ipod touch虽然都是竖屏的,但是却有Retina屏幕和非Retina屏幕之分;另外它们启动画面的尺寸并不是屏幕的大小,而是(屏幕宽度)*(屏幕高度-20)。也就是说,非Retina的尺寸为320*460,Retina屏幕的尺寸为640*920。引入启动画面是支持媒体查询的。因此,可以通过media query给ipad的横竖屏引入不同的图:&link rel="apple-touch-start-image" href="landScape.png" madia="screen and (min-device-width:481px) and (max-device-width:1024px) and (orientation:landscape)" /&&link rel="apple-touch-start-image" href="portait.png" madia="screen and (min-device-width:481px) and (max-device-width:1024px) and (orientation:portait)" /&但是媒体查询却搞不定Retina屏幕,所以通过js来hack:首先,给普通的分辨率引入320*460的图片:&link rel="apple-touch-start-image" href="start.png"media="screen and (max-device-weidth:320px)" /&Retina屏幕js:if((app.device.type === "iPhone" || app.device.type === "iPod")
&& app.device.version &= '5'
&& window.devicePixelRatio &= 2){ $('head').append($('&link rel="apple-touch-startup-image" href="start-640-920.png" /&'));}
GameCenter 使用指南(转)
GameCenter 为单机游戏为主的 iPhone 游戏平台引入了社会化特性,更为将来的网游、多人竞技等游戏打下了基础。下面是 CocoaChina 会员 &ljg420811& 总结的 GameCenter 使用指南,包括 GameCenter 的设置和代码实现。
1.&&& iTunes Connect 设置&&& 首先,申请一个应用程序,不必提交.目地是为了得到Bundle ID.&&& 然后设置一下工程中Info.plist的Bundle identifier使之与iTunes Connect中的Bundle ID相同,否则当你尝试登录GameCenter的时候,会提示一个不支持GameCenter的错误.&&& 申请完毕,打开你刚申请的application,点击Manage Game Center选项.&&& 进入后点击Enable Game Center使你的Game Center生效.&&& 接下来就可以设置自己的Leaderboard和Achievements.
2.&&& Leaderboard设置&&&& 1.sort Order: Leaderboard中的内容是以升序还是降序排列.&&& 2.Score Format Type:分数的类型.&&& 3.*Categories:Leaderboard的一个分数榜,这个可以创建多个,比如游戏可以分为Easy,Normal,Hard三个难度,每个难度一个榜.&&& *设置完成后保存,完成了一个 Leaderboard的设置.我们可以根据需要添加多个 leaderboard.&&& 4.**Score Format Location: leaderboard支持的语言.
&&& **可以支持多种语言,每支持一种语言,需要完成一个上述操作.这个时候右下角会出现save change按钮,点击完成leaderboard的设置.你可以根据需要随时更改你的leaderboard,操作与上述内容类似.
3.&&& Achievements设置
&&& Achievements界面内容比较少,点击左上角的Add New Achievement,打开如下图所示的Achievements创建界面.
&&& Hidden:表示该成就为解锁前玩家是否可见.&&& Achievement ID:程序通过这个属性来识别成就.&&& *Achievement Localization:该成就支持的语言.&&& *Achievement Localization设置如下图所示.&&&& *其中,成就的Image必须是512X512,72DPI的.一切设置完成后,点击save change按钮即完成一个成就的设置.
4.总体功能
在使用各个功能前,你需要了解一下块函数。传送门:
4.1 对Game Center支持判断&& 1. - (BOOL) isGameCenterAvailable&& 2. {&& 3.&&&& Class gcClass = (NSClassFromString(@"GKLocalPlayer"));&& 4.&&&& NSString *reqSysVer = @"4.1";&& 5.&&&& NSString *currSysVer = [[UIDevice currentDevice] systemVersion];&& 6.&&&& BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);&& 7.&&&&&&& 8.&&&& return (gcClass && osVersionSupported);&& 9. }
4.2用户登录&& 1. - (void) authenticateLocalPlayer&& 2. {&& 3.&&&& [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error){&& 4.&&&&&&&& if (error == nil) {&& 5.&&&&&&&&&&&& //成功处理&& 6.&&&&&&&&&&&& NSLog(@"成功");&& 7.&&&&&&&&&&&& NSLog(@"1--alias--.%@",[GKLocalPlayer localPlayer].alias);&& 8.&&&&&&&&&&&& NSLog(@"2--authenticated--.%d",[GKLocalPlayer localPlayer].authenticated);&& 9.&&&&&&&&&&&& NSLog(@"3--isFriend--.%d",[GKLocalPlayer localPlayer].isFriend);& 10.&&&&&&&&&&&& NSLog(@"4--playerID--.%@",[GKLocalPlayer localPlayer].playerID);& 11.&&&&&&&&&&&& NSLog(@"5--underage--.%d",[GKLocalPlayer localPlayer].underage);& 12.&&&&&&&& }else {& 13.&&&&&&&&&&&& //错误处理& 14.&&&&&&&&&&&& NSLog(@"失败& %@",error);& 15.&&&&&&&& }& 16.&&&& }];& 17. }对于开发者来说,Game Center必须经过测试才能上线,没有上线的程序在测试环境中登录时会出现sandbox提示.如图.
4.3用户变更检测由于4.0以后系统支持多任务,玩家的机器有可能被不同的玩家接触,导致Game Center上的用户发生变化,当发生变化的时候,程序必须在游戏中通知玩家.&& 1. - (void) registerForAuthenticationNotification&& 2. {&& 3.&&&& NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];&& 4.&&&& [nc addObserver:self&& 5.&&&&&&&&&&& selector:@selector(authenticationChanged)&& 6.&&&&&&&&&&&&&&& name:GKPlayerAuthenticationDidChangeNotificationName&& 7.&&&&&&&&&&&&& object:nil];&& 8. }&& 9.& 10. - (void) authenticationChanged& 11. {& 12.&&&& if ([GKLocalPlayer localPlayer].isAuthenticated)& 13.&&&& {& 14.&&&&&&&& ;// Insert code here to handle a successful authentication.& 15.&&&& }& 16.&&&& else& 17.&&&& {& 18.&&&&&&&& ;// Insert code here to clean up any outstanding Game Center-related classes.& 19.&&&& }& 20. }
5.对Leaderboard进行操作
5.1上传一个分数&& 1. - (void) reportScore: (int64_t) score forCategory: (NSString*) category&& 2. {&& 3.&&&& GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];&& 4.&&&& scoreReporter.value =&& 5.&&&&&&& 6.&&&& [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {&& 7.&&&&&&&& if (error != nil)&& 8.&&&&&&&& {&& 9.&&&&&&&&&&&& // handle the reporting error& 10.&&&&&&&&&&&& NSLog(@"上传分数出错.");& 11.&&&&&&&&&&&& //If your application receives a network error, you should not discard the score.& 12.&&&&&&&&&&&& //Instead, store the score object and attempt to report the player&s process at& 13.&&&&&&&&&&&& //a later time.& 14.&&&&&&&& }else {& 15.&&&&&&&&&&&& NSLog(@"上传分数成功");& 16.&&&&&&&& }& 17.& 18.&&&& }];& 19. }当上传分数出错的时候,要将上传的分数存储起来,比如将SKScore存入一个NSArray中.等可以上传的时候再次尝试.
5.2下载一个分数&& 1. //GKScore objects provide the data your application needs to create a custom view.&& 2. //Your application can use the score object&s playerID to load the player&s alias.&& 3. //The value property holds the actual value you reported to Game Center. the formattedValue&& 4. //property provides a string with the score value formatted according to the parameters&& 5. //you provided in iTunes Connect.&& 6. - (void) retrieveTopTenScores&& 7. {&& 8.&&&& GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];&& 9.&&&& if (leaderboardRequest != nil)& 10.&&&& {& 11.&&&&&&&& leaderboardRequest.playerScope = GKLeaderboardPlayerScopeG& 12.&&&&&&&& leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllT& 13.&&&&&&&& leaderboardRequest.range = NSMakeRange(1,10);& 14.&&&&&&&& leaderboardRequest.category = @"TS_LB";& 15.&&&&&&&& [leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {& 16.&&&&&&&&&&&& if (error != nil){& 17.&&&&&&&&&&&&&&&& // handle the error.& 18.&&&&&&&&&&&&&&&& NSLog(@"下载失败");& 19.&&&&&&&&&&&& }& 20.&&&&&&&&&&&& if (scores != nil){& 21.&&&&&&&&&&&&&&&& // process the score information.& 22.&&&&&&&&&&&&&&&& NSLog(@"下载成功....");& 23.&&&&&&&&&&&&&&&& NSArray *tempScore = [NSArray arrayWithArray:leaderboardRequest.scores];& 24.&&&&&&&&&&&&&&&& for (GKScore *obj in tempScore) {& 25.&&&&&&&&&&&&&&&&&&&& NSLog(@"&&& playerID&&&&&&&&&&& : %@",obj.playerID);& 26.&&&&&&&&&&&&&&&&&&&& NSLog(@"&&& category&&&&&&&&&&& : %@",obj.category);& 27.&&&&&&&&&&&&&&&&&&&& NSLog(@"&&& date&&&&&&&&&&&&&&& : %@",obj.date);& 28.&&&&&&&&&&&&&&&&&&&& NSLog(@"&&& formattedValue&&& : %@",obj.formattedValue);& 29.&&&&&&&&&&&&&&&&&&&& NSLog(@"&&& value&&&&&&&&&&&&&&& : %d",obj.value);& 30.&&&&&&&&&&&&&&&&&&&& NSLog(@"&&& rank&&&&&&&&&&&&&&& : %d",obj.rank);& 31.&&&&&&&&&&&&&&&&&&&& NSLog(@"**************************************");& 32.&&&&&&&&&&&&&&&& }& 33.&&&&&&&&&&&& }& 34.&&&&&&&& }];& 35.&&&& }& 36. }说明:1)&&& playerScope:表示检索玩家分数范围.2)&&& timeScope:表示某一段时间内的分数3)&&& range:表示分数排名的范围4)&&& category:表示你的Leaderboard的ID.
5.3玩家信息交互Game Center最重要的一个功能就是玩家交互.所以,必须检索已经登录玩家的好友信息.根据自己的需要做出设置,比如,可以与好友比较分数,或者好友排行榜等.//检索已登录用户好友列表&& 1. - (void) retrieveFriends&& 2. {&& 3.&&&& GKLocalPlayer *lp = [GKLocalPlayer localPlayer];&& 4.&&&& if (lp.authenticated)&& 5.&&&& {&& 6.&&&&&&&& [lp loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error) {&& 7.&&&&&&&&&&&& if (error == nil)&& 8.&&&&&&&&&&&& {&& 9.&&&&&&&&&&&&&&&& [self loadPlayerData:friends];& 10.&&&&&&&&&&&& }& 11.&&&&&&&&&&&& else& 12.&&&&&&&&&&&& {& 13.&&&&&&&&&&&&&&&& ;// report an error to the user.& 14.&&&&&&&&&&&& }& 15.&&&&&&&& }];& 16.&&&&&&&&&& 17.&&&& }& 18. }上面的friends得到的只是一个身份列表,里面存储的是NSString,想要转换成好友ID,必须调用- (void) loadPlayerData: (NSArray *) identifiers方法,该方法得到的array里面存储的才是GKPlayer对象.如下&& 1. /*&& 2. Whether you received player identifiers by loading the identifiers for the local player&s&& 3. friends, or from another Game Center class, you must retrieve the details about that player&& 4. from Game Center.&& 5. */&& 6. - (void) loadPlayerData: (NSArray *) identifiers&& 7. {&& 8.&&&& [GKPlayer loadPlayersForIdentifiers:identifiers withCompletionHandler:^(NSArray *players, NSError *error) {&& 9.&&&&&&&& if (error != nil)& 10.&&&&&&&& {& 11.&&&&&&&&&&&& // Handle the error.& 12.&&&&&&&& }& 13.&&&&&&&& if (players != nil)& 14.&&&&&&&& {& 15.&&&&&&&&&&&& NSLog(@"得到好友的alias成功");& 16.&&&&&&&&&&&& GKPlayer *friend1 = [players objectAtIndex:0];& 17.&&&&&&&&&&&& NSLog(@"friedns---alias---%@",friend1.alias);& 18.&&&&&&&&&&&& NSLog(@"friedns---isFriend---%d",friend1.isFriend);& 19.&&&&&&&&&&&& NSLog(@"friedns---playerID---%@",friend1.playerID);& 20.&&&&&&&& }& 21.&&&& }];& 22. }至此,leaderboard功能介绍完毕
6.对Achievement进行操作
& 这一部分内容比较多,而且有的地方有点重复的感觉.6.1汇报一个成就的进度& 对于一个玩家可见的成就,你需要尽可能的报告给玩家解锁的进度;对于一个一部完成的成就,则不需要,当玩家的进度达到100%的时候,会自动解锁该成就.&& 1. - (void) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent&& 2. {&& 3.&&&& GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];&& 4.&&&& if (achievement)&& 5.&&&& {&& 6.&&&&&&&& achievement.percentComplete =&& 7.&&&&&&&& [achievement reportAchievementWithCompletionHandler:^(NSError *error)&& 8.&&&&&&&&& {&& 9.&&&&&&&&&&&&& if (error != nil)& 10.&&&&&&&&&&&&& {& 11.&&&&&&&&&&&&&&&&& //The proper way for your application to handle network errors is retain& 12.&&&&&&&&&&&&&&&&& //the achievement object (possibly adding it to an array). Then, periodically& 13.&&&&&&&&&&&&&&&&& //attempt to report the progress until it is successfully reported.& 14.&&&&&&&&&&&&&&&&& //The GKAchievement class supports the NSCoding protocol to allow your& 15.&&&&&&&&&&&&&&&&& //application to archive an achie& 16.&&&&&&&&&&&&&&&&& NSLog(@"报告成就进度失败 ,错误信息为: \n %@",error);& 17.&&&&&&&&&&&&& }else {& 18.&&&&&&&&&&&&&&&&& //对用户提示,已经完成XX%进度& 19.&&&&&&&&&&&&&&&&& NSLog(@"报告成就进度----&成功!");& 20.&&&&&&&&&&&&&&&&& NSLog(@"&&& completed:%d",achievement.completed);& 21.&&&&&&&&&&&&&&&&& NSLog(@"&&& hidden:%d",achievement.hidden);& 22.&&&&&&&&&&&&&&&&& NSLog(@"&&& lastReportedDate:%@",achievement.lastReportedDate);& 23.&&&&&&&&&&&&&&&&& NSLog(@"&&& percentComplete:%f",achievement.percentComplete);& 24.&&&&&&&&&&&&&&&&& NSLog(@"&&& identifier:%@",achievement.identifier);& 25.&&&&&&&&&&&&& }& 26.&&&&&&&&& }];& 27.&&&& }& 28. }其中该函数的参数中identifier是你成就的ID, percent是该成就完成的百分比
6.2读取一个成就方法一:得到所有的成就&& 1. - (void) loadAchievements&& 2. {&& 3.&&&& NSMutableDictionary *achievementDictionary = [[NSMutableDictionary alloc] init];&& 4.&&&& [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements,NSError *error)&& 5.&&&&& {&& 6.&&&&&&&&& if (error == nil) {&& 7.&&&&&&&&&&&&& NSArray *tempArray = [NSArray arrayWithArray:achievements];&& 8.&&&&&&&&&&&&& for (GKAchievement *tempAchievement in tempArray) {&& 9.&&&&&&&&&&&&&&&&& [achievementDictionary setObject:tempAchievement forKey:tempAchievement.identifier];& 10.&&&&&&&&&&&&&&&&& NSLog(@"&&& completed:%d",tempAchievement.completed);& 11.&&&&&&&&&&&&&&&&& NSLog(@"&&& hidden:%d",tempAchievement.hidden);& 12.&&&&&&&&&&&&&&&&& NSLog(@"&&& lastReportedDate:%@",tempAchievement.lastReportedDate);& 13.&&&&&&&&&&&&&&&&& NSLog(@"&&& percentComplete:%f",tempAchievement.percentComplete);& 14.&&&&&&&&&&&&&&&&& NSLog(@"&&& identifier:%@",tempAchievement.identifier);& 15.&&&&&&&&&&&&& }& 16.&&&&&&&&& }& 17.&&&&& }];& 18. }函数中NSArray返回的是你的所有成就ID.
方法二:根据ID获取成就&& 1. - (GKAchievement*) getAchievementForIdentifier: (NSString*) identifier&& 2. {&& 3.&&&& NSMutableDictionary *achievementDictionary = [[NSMutableDictionary alloc] init];&& 4.&&&& GKAchievement *achievement = [achievementDictionary objectForKey:identifier];&& 5.&&&& if (achievement == nil)&& 6.&&&& {&& 7.&&&&&&&& achievement = [[[GKAchievement alloc] initWithIdentifier:identifier] autorelease];&& 8.&&&&&&&& [achievementDictionary setObject:achievement forKey:achievement.identifier];&& 9.&&&& }& 10.&&&& return [[achievement retain] autorelease];& 11. }
6.3获取成就描述和图片在自定义界面中,玩家需要一个成就描述,以及该成就的图片,Game Center提供了该功能.当然,你也可以自己在程序中完成,毕竟玩家不可能时刻处于在线状态.&& 1. - (NSArray*)retrieveAchievmentMetadata&& 2. {&& 3.&&&& //读取成就的描述&& 4.&&&& [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:&& 5.&&&&& ^(NSArray *descriptions, NSError *error) {&& 6.&&&&&&&&& if (error != nil)&& 7.&&&&&&&&& {&& 8.&&&&&&&&&&&&& // process the errors&& 9.&&&&&&&&&&&&& NSLog(@"读取成就说明出错");& 10.&&&&&&&&& }& 11.&&&&&&&&& if (descriptions != nil)& 12.&&&&&&&&& {& 13.&&&&&&&&&&&&& // use the achievement descriptions.& 14.&&&&&&&&&&&&& for (GKAchievementDescription *achDescription in descriptions) {& 15.&&&&&&&&&&&&&&&&& NSLog(@"1..identifier..%@",achDescription.identifier);& 16.&&&&&&&&&&&&&&&&& NSLog(@"2..achievedDescription..%@",achDescription.achievedDescription);& 17.&&&&&&&&&&&&&&&&& NSLog(@"3..title..%@",achDescription.title);& 18.&&&&&&&&&&&&&&&&& NSLog(@"4..unachievedDescription..%@",achDescription.unachievedDescription);& 19.&&&&&&&&&&&&&&&&& NSLog(@"5............%@",achDescription.image);& 20.&&&&&&&&&&&&&&&&&& 21.&&&&&&&&&&&&&&&&& //获取成就图片,如果成就未解锁,返回一个大文号& 22.&&&&&&&&&&&&&&&&& /*& 23.&&&&&&&&&&&&&&&&& [achDescription loadImageWithCompletionHandler:^(UIImage *image, NSError *error) {& 24.&&&&&&&&&&&&&&&&&&&&& if (error == nil)& 25.&&&&&&&&&&&&&&&&&&&&& {& 26.&&&&&&&&&&&&&&&&&&&&&&&&& // use the loaded image. The image property is also populated with the same image.& 27.&&&&&&&&&&&&&&&&&&&&&&&&& NSLog(@"成功取得成就的图片");& 28.&&&&&&&&&&&&&&&&&&&&&&&&& UIImage *aImage =& 29.&&&&&&&&&&&&&&&&&&&&&&&&& UIImageView *aView = [[UIImageView alloc] initWithImage:aImage];& 30.&&&&&&&&&&&&&&&&&&&&&&&&& aView.frame = CGRectMake(50, 50, 200, 200);& 31.&&&&&&&&&&&&&&&&&&&&&&&&& aView.backgroundColor = [UIColor clearColor];& 32.&&&&&&&&&&&&&&&&&&&&&&&&& [[[CCDirector sharedDirector] openGLView] addSubview:aView];& 33.&&&&&&&&&&&&&&&&&&&&& }else {& 34.&&&&&&&&&&&&&&&&&&&&&&&&& NSLog(@"获得成就图片失败");& 35.&&&&&&&&&&&&&&&&&&&&& }& 36.&&&&&&&&&&&&&&&&& }];& 37.&&&&&&&&&&&&&&&&&& */& 38.&&&&&&&&&&&&& }& 39.&&&&&&&&& }& 40.&&&& }];& 41.&&&&& 42. }如果你不主动使用注释中的方法,那么你得到的description中不会有图片,这样可以减少网络的使用,尽量少下载东西.当使用注释中的代码时,如果成就已经解锁,则返回该成就的图标,如果没有解锁,则返回一个大问号,至于未解锁图标是否可以自定义,我找寻的结果好像是不可以.转自:http://www.cocoachina.com/gamedev/misc/29.html
KVO/KVC做了简单的介绍(转)
对kvo/kvc做了简单的介绍,可作为入门读物。
有些术语描述不够精确请指正。
欢迎讨论。
Kvo是Cocoa的一个重要机制,他提供了观察某一属性变化的方法,极大的简化了代码。这种观察-被观察模型适用于这样的情况,比方说根据A(数 据类)的某个属性值变化,B(view类)中的某个属性做出相应变化。对于推崇MVC的cocoa而言,kvo应用的地方非常广泛。(这样的机制听起来类 似Notification,但是notification是需要一个发送notification的对象,一般是 notificationCenter,来通知观察者。而kvo是直接通知到观察对象。)
适用kvo时,通常遵循如下流程:
-(void)addObserver:(NSObject&*)anObserver forKeyPath:(NSString&*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context
keyPath就是要观察的属性值,options给你观察键值变化的选择,而context方便传输你需要的数据(注意这是一个void型)
2 实现变化方法:
-(void) observeValueForKeyPath:(NSString&*)keyPath ofObject:(id)objectchange:(NSDictionary&*)change context:(void*)context
change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。
是不是很简单?kvo的逻辑非常清晰,实现步骤简单。
说了这么多,大家都要跃跃欲试了吧。可是,在此之前,我们还需要了解KVC机制。其实,知道了kvo的逻辑只是帮助你理解而已,要真正掌握的,不在 于kvo的实现步骤是什么,而在于KVC,因为只有符合KVC标准的对象才能使用kvo(强烈推荐要使用kvo的人先理解KVC)。
KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor方法或是直接访问成员对象。
key就是确定对象某个值的字符串,它通常和accessor方法或是变量同名,并且必须以小写字母开头。Key path就是以&.&分隔的key,因为属性值也能包含属性。比如我们可以person这样的key,也可以有key.gender这样的key path。
获取属性值时可以通过valueForKey:的方法,设置属性值用setValue:forKey:。与此同时,KVC还对未定义的属性值定义了 valueForUndefinedKey:,你可以重载以获取你要的实现(补充下,KVC定义载NSKeyValueCoding的非正式协议里)。
在O-C 2.0引入了property,我们也可以通过.运算符来访问属性。下面直接看个例子:
@property NSI
instance.number&=3;[instance setValue:[NSNumber numberWithInteger:3] forKey:@"number"];
注意KVC中的value都必须是对象。
以上介绍了通过KVC来获取/设置属性,接下来要说明下实现KVC的访问器方法(accessor method)。Apple给出的惯例通常是:
-key:,以及setKey:(使用的name convention和setter/getter命名一致)。对于未定义的属性可以用setNilValueForKey:。
至此,KVC的基本概念你应该已经掌握了。之所以是基本,因为只涉及到了单值情况,kvc还可以运用到对多关系,这里就不说了,留给各位自我学习的空间
接下来,我们要以集合为例,来对掌握的KVC进行一下实践。
之所以选择array,因为在ios中,array往往做为tableview的数据源,有这样的一种情况:
&假设我们已经有N条数据,在进行了某个操作后,有在原先的数据后多了2条记录;或者对N中的某些数据进行更新替换。不使用KVC我们可以使用 reloadData方法或reloadRowsAtIndexPaths。前一种的弊端在于如果N很大消耗就很大。试想你只添加了几条数据却要重载之前 N数据。后一种方法的不足在于代码会很冗余,你要一次计算各个indexPath再去reload,而且还要提前想好究竟在哪些情况下会引起数据更新,
倘若使用了KVC/kvo,这样的麻烦就迎刃而解了,你将不用关心追加或是更新多少条数据。
下面将以添加数据为例,说明需要实现的方法:
实现insertObject:inKeyAtIndex:或者insertKey:atIndexes。同时在kvo中我们可以通过change这个dictionary得知发生了哪种变化,从而进行相应的处理。
另附关于KVC/KVO的资料:
新增加一个例子:
关于xcode里资源文件夹管理(转)
&xcode里的新建的一个分组文件夹(黄色的),并不是真正在目录下就有一个这样的文件夹,里面的文件还是放在一个目录下。然而有时候项目要用到的资源很多,有时候还会有重名的情况,这样如果放在分组文件夹里就不好了。为了方便管理我们有必要在目录下新建一些}

我要回帖

更多关于 手机只能关机才能充电 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信